1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006-2017 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 <https://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 xftfont_list (struct frame
*f
, Lisp_Object spec
)
131 Lisp_Object list
= ftfont_list (f
, spec
);
133 for (Lisp_Object tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
134 ASET (XCAR (tail
), FONT_TYPE_INDEX
, Qxft
);
139 xftfont_match (struct frame
*f
, Lisp_Object spec
)
141 Lisp_Object entity
= ftfont_match (f
, spec
);
144 ASET (entity
, FONT_TYPE_INDEX
, Qxft
);
148 static FcChar8 ascii_printable
[95];
151 xftfont_fix_match (FcPattern
*pat
, FcPattern
*match
)
153 /* These values are not used for matching (except antialias), but for
154 rendering, so make sure they are carried over to the match.
155 We also put antialias here because most fonts are antialiased, so
156 the match will have antialias true. */
162 FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b
);
165 FcPatternDel (match
, FC_ANTIALIAS
);
166 FcPatternAddBool (match
, FC_ANTIALIAS
, FcFalse
);
168 FcPatternGetBool (pat
, FC_HINTING
, 0, &b
);
171 FcPatternDel (match
, FC_HINTING
);
172 FcPatternAddBool (match
, FC_HINTING
, FcFalse
);
174 #ifndef FC_HINT_STYLE
175 # define FC_HINT_STYLE "hintstyle"
177 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i
))
179 FcPatternDel (match
, FC_HINT_STYLE
);
180 FcPatternAddInteger (match
, FC_HINT_STYLE
, i
);
182 #ifndef FC_LCD_FILTER
183 /* Older fontconfig versions don't have FC_LCD_FILTER. */
184 #define FC_LCD_FILTER "lcdfilter"
186 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i
))
188 FcPatternDel (match
, FC_LCD_FILTER
);
189 FcPatternAddInteger (match
, FC_LCD_FILTER
, i
);
191 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_RGBA
, 0, &i
))
193 FcPatternDel (match
, FC_RGBA
);
194 FcPatternAddInteger (match
, FC_RGBA
, i
);
196 if (FcResultMatch
== FcPatternGetDouble (pat
, FC_DPI
, 0, &dpi
))
198 FcPatternDel (match
, FC_DPI
);
199 FcPatternAddDouble (match
, FC_DPI
, dpi
);
204 xftfont_add_rendering_parameters (FcPattern
*pat
, Lisp_Object entity
)
209 for (tail
= AREF (entity
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
211 Lisp_Object key
= XCAR (XCAR (tail
));
212 Lisp_Object val
= XCDR (XCAR (tail
));
214 if (EQ (key
, QCantialias
))
215 FcPatternAddBool (pat
, FC_ANTIALIAS
, NILP (val
) ? FcFalse
: FcTrue
);
216 else if (EQ (key
, QChinting
))
217 FcPatternAddBool (pat
, FC_HINTING
, NILP (val
) ? FcFalse
: FcTrue
);
218 else if (EQ (key
, QCautohint
))
219 FcPatternAddBool (pat
, FC_AUTOHINT
, NILP (val
) ? FcFalse
: FcTrue
);
220 else if (EQ (key
, QChintstyle
))
223 FcPatternAddInteger (pat
, FC_HINT_STYLE
, XINT (val
));
224 else if (SYMBOLP (val
)
225 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
226 FcPatternAddInteger (pat
, FC_HINT_STYLE
, ival
);
228 else if (EQ (key
, QCrgba
))
231 FcPatternAddInteger (pat
, FC_RGBA
, XINT (val
));
232 else if (SYMBOLP (val
)
233 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
234 FcPatternAddInteger (pat
, FC_RGBA
, ival
);
236 else if (EQ (key
, QClcdfilter
))
239 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
= XINT (val
));
240 else if (SYMBOLP (val
)
241 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
242 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
);
245 else if (EQ (key
, QCembolden
))
246 FcPatternAddBool (pat
, FC_EMBOLDEN
, NILP (val
) ? FcFalse
: FcTrue
);
252 xftfont_open (struct frame
*f
, Lisp_Object entity
, int pixel_size
)
255 Display
*display
= FRAME_X_DISPLAY (f
);
256 Lisp_Object val
, filename
, idx
, font_object
;
257 FcPattern
*pat
= NULL
, *match
;
258 struct xftfont_info
*xftfont_info
= NULL
;
261 XftFont
*xftfont
= NULL
;
268 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
272 filename
= XCAR (val
);
274 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
277 pat
= FcPatternCreate ();
278 FcPatternAddInteger (pat
, FC_WEIGHT
, FONT_WEIGHT_NUMERIC (entity
));
279 i
= FONT_SLANT_NUMERIC (entity
) - 100;
281 FcPatternAddInteger (pat
, FC_SLANT
, i
);
282 FcPatternAddInteger (pat
, FC_WIDTH
, FONT_WIDTH_NUMERIC (entity
));
283 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
284 val
= AREF (entity
, FONT_FAMILY_INDEX
);
286 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
287 val
= AREF (entity
, FONT_FOUNDRY_INDEX
);
289 FcPatternAddString (pat
, FC_FOUNDRY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
290 val
= AREF (entity
, FONT_SPACING_INDEX
);
292 FcPatternAddInteger (pat
, FC_SPACING
, XINT (val
));
293 val
= AREF (entity
, FONT_DPI_INDEX
);
296 double dbl
= XINT (val
);
298 FcPatternAddDouble (pat
, FC_DPI
, dbl
);
300 val
= AREF (entity
, FONT_AVGWIDTH_INDEX
);
301 if (INTEGERP (val
) && XINT (val
) == 0)
302 FcPatternAddBool (pat
, FC_SCALABLE
, FcTrue
);
303 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
304 over 10x20-ISO8859-1.pcf.gz). */
305 FcPatternAddCharSet (pat
, FC_CHARSET
, ftfont_get_fc_charset (entity
));
307 xftfont_add_rendering_parameters (pat
, entity
);
309 FcPatternAddString (pat
, FC_FILE
, (FcChar8
*) SDATA (filename
));
310 FcPatternAddInteger (pat
, FC_INDEX
, XINT (idx
));
315 /* Substitute in values from X resources and XftDefaultSet. */
316 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
317 match
= XftFontMatch (display
, FRAME_X_SCREEN_NUMBER (f
), pat
, &result
);
318 xftfont_fix_match (pat
, match
);
320 FcPatternDestroy (pat
);
321 xftfont
= XftFontOpenPattern (display
, match
);
325 XftPatternDestroy (match
);
328 ft_face
= XftLockFace (xftfont
);
331 /* We should not destroy PAT here because it is kept in XFTFONT and
332 destroyed automatically when XFTFONT is closed. */
333 font_object
= font_build_object (VECSIZE (struct xftfont_info
),
335 ASET (font_object
, FONT_FILE_INDEX
, filename
);
336 font
= XFONT_OBJECT (font_object
);
337 font
->pixel_size
= size
;
338 font
->driver
= &xftfont_driver
;
339 font
->encoding_charset
= font
->repertory_charset
= -1;
341 xftfont_info
= (struct xftfont_info
*) font
;
342 xftfont_info
->display
= display
;
343 xftfont_info
->xftfont
= xftfont
;
344 xftfont_info
->x_display_id
= FRAME_DISPLAY_INFO (f
)->x_id
;
345 /* This means that there's no need of transformation. */
346 xftfont_info
->matrix
.xx
= 0;
347 if (FcPatternGetMatrix (xftfont
->pattern
, FC_MATRIX
, 0, &matrix
)
350 xftfont_info
->matrix
.xx
= 0x10000L
* matrix
->xx
;
351 xftfont_info
->matrix
.yy
= 0x10000L
* matrix
->yy
;
352 xftfont_info
->matrix
.xy
= 0x10000L
* matrix
->xy
;
353 xftfont_info
->matrix
.yx
= 0x10000L
* matrix
->yx
;
355 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
356 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
358 spacing
= FC_PROPORTIONAL
;
359 if (! ascii_printable
[0])
362 for (ch
= 0; ch
< 95; ch
++)
363 ascii_printable
[ch
] = ' ' + ch
;
367 /* Unfortunately Xft doesn't provide a way to get minimum char
368 width. So, we set min_width to space_width. */
370 if (spacing
!= FC_PROPORTIONAL
372 && spacing
!= FC_DUAL
376 font
->min_width
= font
->max_width
= font
->average_width
377 = font
->space_width
= xftfont
->max_advance_width
;
378 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
382 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
383 font
->min_width
= font
->max_width
= font
->space_width
385 if (font
->space_width
<= 0)
386 /* dirty workaround */
387 font
->space_width
= pixel_size
;
388 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
389 font
->average_width
= (font
->space_width
+ extents
.xOff
) / 95;
393 font
->ascent
= xftfont
->ascent
;
394 font
->descent
= xftfont
->descent
;
395 /* The following workaround is unnecessary on most systems, and
396 causes annoying differences in glyph height between regular and
397 bold fonts (see bug#22383). However, with some fonts, such as
398 monaco, removing the workaround results in overlapping vertical
399 space of a line, see bug#23360. As long as the way to reconcile
400 these opposites is not known, we provide a user option to work
401 around the problem. */
403 && xft_font_ascent_descent_override
)
405 /* The above condition is a dirty workaround because
406 XftTextExtents8 behaves strangely for some fonts
407 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
408 if (font
->ascent
< extents
.y
)
409 font
->ascent
= extents
.y
;
410 if (font
->descent
< extents
.height
- extents
.y
)
411 font
->descent
= extents
.height
- extents
.y
;
413 font
->height
= font
->ascent
+ font
->descent
;
415 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) == 0)
417 int upEM
= ft_face
->units_per_EM
;
419 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
420 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
421 if (font
->underline_thickness
> 2)
422 font
->underline_position
-= font
->underline_thickness
/ 2;
426 font
->underline_position
= -1;
427 font
->underline_thickness
= 0;
430 xftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
431 xftfont_info
->otf
= NULL
;
432 #endif /* HAVE_LIBOTF */
433 xftfont_info
->ft_size
= ft_face
->size
;
435 font
->baseline_offset
= 0;
436 font
->relative_compose
= 0;
437 font
->default_ascent
= 0;
438 font
->vertical_centering
= false;
440 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
444 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
445 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
446 font
->baseline_offset
= rec
.u
.integer
;
447 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
448 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
449 font
->relative_compose
= rec
.u
.integer
;
450 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
451 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
452 font
->default_ascent
= rec
.u
.integer
;
460 xftfont_close (struct font
*font
)
462 struct x_display_info
*xdi
;
463 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
466 if (xftfont_info
->otf
)
468 OTF_close (xftfont_info
->otf
);
469 xftfont_info
->otf
= NULL
;
473 /* See comment in xfont_close. */
474 if (xftfont_info
->xftfont
475 && ((xdi
= x_display_info_for_display (xftfont_info
->display
))
476 && xftfont_info
->x_display_id
== xdi
->x_id
))
479 XftUnlockFace (xftfont_info
->xftfont
);
480 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
482 xftfont_info
->xftfont
= NULL
;
487 xftfont_prepare_face (struct frame
*f
, struct face
*face
)
489 struct xftface_info
*xftface_info
;
492 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
493 if (face
!= face
->ascii_face
)
495 face
->extra
= face
->ascii_face
->extra
;
500 xftface_info
= xmalloc (sizeof *xftface_info
);
501 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
502 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
503 face
->extra
= xftface_info
;
507 xftfont_done_face (struct frame
*f
, struct face
*face
)
509 struct xftface_info
*xftface_info
;
512 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
513 if (face
!= face
->ascii_face
518 xftface_info
= (struct xftface_info
*) face
->extra
;
521 xfree (xftface_info
);
527 xftfont_has_char (Lisp_Object font
, int c
)
529 struct xftfont_info
*xftfont_info
;
530 struct charset
*cs
= NULL
;
532 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
533 && charset_jisx0208
>= 0)
534 cs
= CHARSET_FROM_ID (charset_jisx0208
);
535 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
536 && charset_ksc5601
>= 0)
537 cs
= CHARSET_FROM_ID (charset_ksc5601
);
539 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
541 if (FONT_ENTITY_P (font
))
542 return ftfont_has_char (font
, c
);
543 xftfont_info
= (struct xftfont_info
*) XFONT_OBJECT (font
);
544 return (XftCharExists (xftfont_info
->display
, xftfont_info
->xftfont
,
545 (FcChar32
) c
) == FcTrue
);
549 xftfont_encode_char (struct font
*font
, int c
)
551 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
552 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
555 return (code
? code
: FONT_INVALID_CODE
);
559 xftfont_text_extents (struct font
*font
, unsigned int *code
,
560 int nglyphs
, struct font_metrics
*metrics
)
562 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
566 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
570 metrics
->lbearing
= - extents
.x
;
571 metrics
->rbearing
= - extents
.x
+ extents
.width
;
572 metrics
->width
= extents
.xOff
;
573 metrics
->ascent
= extents
.y
;
574 metrics
->descent
= extents
.height
- extents
.y
;
578 xftfont_get_xft_draw (struct frame
*f
)
580 XftDraw
*xft_draw
= font_get_frame_data (f
, Qxft
);
585 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
586 FRAME_X_DRAWABLE (f
),
588 FRAME_X_COLORMAP (f
));
590 eassert (xft_draw
!= NULL
);
591 font_put_frame_data (f
, Qxft
, xft_draw
);
597 xftfont_draw (struct glyph_string
*s
, int from
, int to
, int x
, int y
,
598 bool with_background
)
602 struct frame
*f
= s
->f
;
603 struct face
*face
= s
->face
;
604 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
605 struct xftface_info
*xftface_info
= NULL
;
606 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
612 if (s
->font
== face
->font
)
613 xftface_info
= (struct xftface_info
*) face
->extra
;
614 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
615 &fg
, with_background
? &bg
: NULL
);
616 if (s
->num_clips
> 0)
617 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
619 XftDrawSetClip (xft_draw
, NULL
);
623 int height
= FONT_HEIGHT (s
->font
), ascent
= FONT_BASE (s
->font
);
625 /* Font's global height and ascent values might be
626 preposterously large for some fonts. We fix here the case
627 when those fonts are used for display of glyphless
628 characters, because drawing background with font dimensions
629 in those cases makes the display illegible. There's only one
630 more call to the draw method with with_background set to
631 true, and that's in x_draw_glyph_string_foreground, when
632 drawing the cursor, where we have no such heuristics
634 if (s
->first_glyph
->type
== GLYPHLESS_GLYPH
635 && (s
->first_glyph
->u
.glyphless
.method
== GLYPHLESS_DISPLAY_HEX_CODE
636 || s
->first_glyph
->u
.glyphless
.method
== GLYPHLESS_DISPLAY_ACRONYM
))
638 s
->first_glyph
->slice
.glyphless
.lower_yoff
639 - s
->first_glyph
->slice
.glyphless
.upper_yoff
;
640 XftDrawRect (xft_draw
, &bg
, x
, y
- ascent
, s
->width
, height
);
642 code
= alloca (sizeof (FT_UInt
) * len
);
643 for (i
= 0; i
< len
; i
++)
644 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
645 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
648 for (i
= 0; i
< len
; i
++)
649 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
650 x
+ i
, y
, code
+ i
, 1);
652 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
654 /* Need to explicitly mark the frame dirty because we didn't call
655 FRAME_X_DRAWABLE in order to draw: we cached the drawable in the
656 XftDraw structure. */
657 x_mark_frame_dirty (f
);
662 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
664 xftfont_shape (Lisp_Object lgstring
)
666 struct font
*font
= CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
));
667 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
668 FT_Face ft_face
= XftLockFace (xftfont_info
->xftfont
);
669 xftfont_info
->ft_size
= ft_face
->size
;
670 Lisp_Object val
= ftfont_shape (lgstring
);
671 XftUnlockFace (xftfont_info
->xftfont
);
677 xftfont_end_for_frame (struct frame
*f
)
682 xft_draw
= font_get_frame_data (f
, Qxft
);
686 XftDrawDestroy (xft_draw
);
688 font_put_frame_data (f
, Qxft
, NULL
);
694 /* When using X double buffering, the XftDraw structure we build
695 seems to be useless once a frame is resized, so recreate it on
696 ConfigureNotify and in some other cases. */
699 xftfont_drop_xrender_surfaces (struct frame
*f
)
702 if (FRAME_X_DOUBLE_BUFFERED_P (f
))
703 xftfont_end_for_frame (f
);
708 xftfont_cached_font_ok (struct frame
*f
, Lisp_Object font_object
,
711 struct xftfont_info
*info
= (struct xftfont_info
*) XFONT_OBJECT (font_object
);
712 FcPattern
*oldpat
= info
->xftfont
->pattern
;
713 Display
*display
= FRAME_X_DISPLAY (f
);
714 FcPattern
*pat
= FcPatternCreate ();
719 xftfont_add_rendering_parameters (pat
, entity
);
720 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
722 r1
= FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b1
);
723 r2
= FcPatternGetBool (oldpat
, FC_ANTIALIAS
, 0, &b2
);
724 if (r1
!= r2
|| b1
!= b2
) goto out
;
725 r1
= FcPatternGetBool (pat
, FC_HINTING
, 0, &b1
);
726 r2
= FcPatternGetBool (oldpat
, FC_HINTING
, 0, &b2
);
727 if (r1
!= r2
|| b1
!= b2
) goto out
;
728 r1
= FcPatternGetBool (pat
, FC_AUTOHINT
, 0, &b1
);
729 r2
= FcPatternGetBool (oldpat
, FC_AUTOHINT
, 0, &b2
);
730 if (r1
!= r2
|| b1
!= b2
) goto out
;
732 r1
= FcPatternGetBool (pat
, FC_EMBOLDEN
, 0, &b1
);
733 r2
= FcPatternGetBool (oldpat
, FC_EMBOLDEN
, 0, &b2
);
734 if (r1
!= r2
|| b1
!= b2
) goto out
;
736 r1
= FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i1
);
737 r2
= FcPatternGetInteger (oldpat
, FC_HINT_STYLE
, 0, &i2
);
738 if (r1
!= r2
|| i1
!= i2
) goto out
;
739 r1
= FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i1
);
740 r2
= FcPatternGetInteger (oldpat
, FC_LCD_FILTER
, 0, &i2
);
741 if (r1
!= r2
|| i1
!= i2
) goto out
;
742 r1
= FcPatternGetInteger (pat
, FC_RGBA
, 0, &i1
);
743 r2
= FcPatternGetInteger (oldpat
, FC_RGBA
, 0, &i2
);
744 if (r1
!= r2
|| i1
!= i2
) goto out
;
748 FcPatternDestroy (pat
);
752 struct font_driver
const xftfont_driver
=
754 /* We can't draw a text without device dependent functions. */
755 .type
= LISPSYM_INITIALLY (Qxft
),
756 .get_cache
= xfont_get_cache
,
757 .list
= xftfont_list
,
758 .match
= xftfont_match
,
759 .list_family
= ftfont_list_family
,
760 .open
= xftfont_open
,
761 .close
= xftfont_close
,
762 .prepare_face
= xftfont_prepare_face
,
763 .done_face
= xftfont_done_face
,
764 .has_char
= xftfont_has_char
,
765 .encode_char
= xftfont_encode_char
,
766 .text_extents
= xftfont_text_extents
,
767 .draw
= xftfont_draw
,
768 .get_bitmap
= ftfont_get_bitmap
,
769 .anchor_point
= ftfont_anchor_point
,
771 .otf_capability
= ftfont_otf_capability
,
773 .end_for_frame
= xftfont_end_for_frame
,
774 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
775 .shape
= xftfont_shape
,
777 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
778 .get_variation_glyphs
= ftfont_variation_glyphs
,
780 .filter_properties
= ftfont_filter_properties
,
781 .cached_font_ok
= xftfont_cached_font_ok
,
782 .combining_capability
= ftfont_combining_capability
,
783 .drop_xrender_surfaces
= xftfont_drop_xrender_surfaces
,
787 syms_of_xftfont (void)
789 DEFSYM (Qxft
, "xft");
790 DEFSYM (QChinting
, ":hinting");
791 DEFSYM (QCautohint
, ":autohint");
792 DEFSYM (QChintstyle
, ":hintstyle");
793 DEFSYM (QCrgba
, ":rgba");
794 DEFSYM (QCembolden
, ":embolden");
795 DEFSYM (QClcdfilter
, ":lcdfilter");
797 DEFVAR_BOOL ("xft-font-ascent-descent-override",
798 xft_font_ascent_descent_override
,
799 doc
: /* Non-nil means override the ascent and descent values for Xft font driver.
800 This is needed with some fonts to correct vertical overlap of glyphs. */);
801 xft_font_ascent_descent_override
= 0;
803 ascii_printable
[0] = 0;
805 register_font_driver (&xftfont_driver
, NULL
);