1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006-2011 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/>. */
26 #include <X11/Xft/Xft.h>
29 #include "dispextern.h"
32 #include "blockinput.h"
33 #include "character.h"
35 #include "composite.h"
40 /* Xft font driver. */
42 static Lisp_Object Qxft
;
43 static Lisp_Object QChinting
, QCautohint
, QChintstyle
, QCrgba
, QCembolden
,
46 /* The actual structure for Xft font that can be casted to struct
52 /* The following five members must be here in this order to be
53 compatible with struct ftfont_info (in ftfont.c). */
55 int maybe_otf
; /* Flag to tell if this may be OTF or not. */
57 #endif /* HAVE_LIBOTF */
66 /* Structure pointed by (struct face *)->extra */
70 XftColor xft_fg
; /* color for face->foreground */
71 XftColor xft_bg
; /* color for face->background */
74 static void xftfont_get_colors (FRAME_PTR
, struct face
*, GC gc
,
75 struct xftface_info
*,
76 XftColor
*fg
, XftColor
*bg
);
79 /* Setup foreground and background colors of GC into FG and BG. If
80 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
84 xftfont_get_colors (FRAME_PTR f
, struct face
*face
, GC gc
, struct xftface_info
*xftface_info
, XftColor
*fg
, XftColor
*bg
)
86 if (xftface_info
&& face
->gc
== gc
)
88 *fg
= xftface_info
->xft_fg
;
90 *bg
= xftface_info
->xft_bg
;
95 int fg_done
= 0, bg_done
= 0;
98 XGetGCValues (FRAME_X_DISPLAY (f
), gc
,
99 GCForeground
| GCBackground
, &xgcv
);
102 if (xgcv
.foreground
== face
->foreground
)
103 *fg
= xftface_info
->xft_fg
, fg_done
= 1;
104 else if (xgcv
.foreground
== face
->background
)
105 *fg
= xftface_info
->xft_bg
, fg_done
= 1;
108 else if (xgcv
.background
== face
->background
)
109 *bg
= xftface_info
->xft_bg
, bg_done
= 1;
110 else if (xgcv
.background
== face
->foreground
)
111 *bg
= xftface_info
->xft_fg
, bg_done
= 1;
114 if (fg_done
+ bg_done
< 2)
118 colors
[0].pixel
= fg
->pixel
= xgcv
.foreground
;
120 colors
[1].pixel
= bg
->pixel
= xgcv
.background
;
121 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
,
123 fg
->color
.alpha
= 0xFFFF;
124 fg
->color
.red
= colors
[0].red
;
125 fg
->color
.green
= colors
[0].green
;
126 fg
->color
.blue
= colors
[0].blue
;
129 bg
->color
.alpha
= 0xFFFF;
130 bg
->color
.red
= colors
[1].red
;
131 bg
->color
.green
= colors
[1].green
;
132 bg
->color
.blue
= colors
[1].blue
;
140 static Lisp_Object
xftfont_list (Lisp_Object
, Lisp_Object
);
141 static Lisp_Object
xftfont_match (Lisp_Object
, Lisp_Object
);
142 static Lisp_Object
xftfont_open (FRAME_PTR
, Lisp_Object
, int);
143 static void xftfont_close (FRAME_PTR
, struct font
*);
144 static int xftfont_prepare_face (FRAME_PTR
, struct face
*);
145 static void xftfont_done_face (FRAME_PTR
, struct face
*);
146 static int xftfont_has_char (Lisp_Object
, int);
147 static unsigned xftfont_encode_char (struct font
*, int);
148 static int xftfont_text_extents (struct font
*, unsigned *, int,
149 struct font_metrics
*);
150 static int xftfont_draw (struct glyph_string
*, int, int, int, int, int);
151 static int xftfont_end_for_frame (FRAME_PTR f
);
153 struct font_driver xftfont_driver
;
156 xftfont_list (Lisp_Object frame
, Lisp_Object spec
)
158 Lisp_Object list
= ftfont_driver
.list (frame
, spec
), tail
;
160 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
161 ASET (XCAR (tail
), FONT_TYPE_INDEX
, Qxft
);
166 xftfont_match (Lisp_Object frame
, Lisp_Object spec
)
168 Lisp_Object entity
= ftfont_driver
.match (frame
, spec
);
171 ASET (entity
, FONT_TYPE_INDEX
, Qxft
);
175 static FcChar8 ascii_printable
[95];
178 xftfont_fix_match (FcPattern
*pat
, FcPattern
*match
)
180 /* These values are not used for matching (except antialias), but for
181 rendering, so make sure they are carried over to the match.
182 We also put antialias here because most fonts are antialiased, so
183 the match will have antialias true. */
189 FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b
);
192 FcPatternDel (match
, FC_ANTIALIAS
);
193 FcPatternAddBool (match
, FC_ANTIALIAS
, FcFalse
);
195 FcPatternGetBool (pat
, FC_HINTING
, 0, &b
);
198 FcPatternDel (match
, FC_HINTING
);
199 FcPatternAddBool (match
, FC_HINTING
, FcFalse
);
201 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i
))
203 FcPatternDel (match
, FC_HINT_STYLE
);
204 FcPatternAddInteger (match
, FC_HINT_STYLE
, i
);
206 #ifndef FC_LCD_FILTER
207 /* Older fontconfig versions don't have FC_LCD_FILTER. */
208 #define FC_LCD_FILTER "lcdfilter"
210 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i
))
212 FcPatternDel (match
, FC_LCD_FILTER
);
213 FcPatternAddInteger (match
, FC_LCD_FILTER
, i
);
215 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_RGBA
, 0, &i
))
217 FcPatternDel (match
, FC_RGBA
);
218 FcPatternAddInteger (match
, FC_RGBA
, i
);
220 if (FcResultMatch
== FcPatternGetDouble (pat
, FC_DPI
, 0, &dpi
))
222 FcPatternDel (match
, FC_DPI
);
223 FcPatternAddDouble (match
, FC_DPI
, dpi
);
228 xftfont_add_rendering_parameters (FcPattern
*pat
, Lisp_Object entity
)
233 for (tail
= AREF (entity
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
235 Lisp_Object key
= XCAR (XCAR (tail
));
236 Lisp_Object val
= XCDR (XCAR (tail
));
238 if (EQ (key
, QCantialias
))
239 FcPatternAddBool (pat
, FC_ANTIALIAS
, NILP (val
) ? FcFalse
: FcTrue
);
240 else if (EQ (key
, QChinting
))
241 FcPatternAddBool (pat
, FC_HINTING
, NILP (val
) ? FcFalse
: FcTrue
);
242 else if (EQ (key
, QCautohint
))
243 FcPatternAddBool (pat
, FC_AUTOHINT
, NILP (val
) ? FcFalse
: FcTrue
);
244 else if (EQ (key
, QChintstyle
))
247 FcPatternAddInteger (pat
, FC_HINT_STYLE
, XINT (val
));
248 else if (SYMBOLP (val
)
249 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
250 FcPatternAddInteger (pat
, FC_HINT_STYLE
, ival
);
252 else if (EQ (key
, QCrgba
))
255 FcPatternAddInteger (pat
, FC_RGBA
, XINT (val
));
256 else if (SYMBOLP (val
)
257 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
258 FcPatternAddInteger (pat
, FC_RGBA
, ival
);
260 else if (EQ (key
, QClcdfilter
))
263 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
= XINT (val
));
264 else if (SYMBOLP (val
)
265 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
266 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
);
269 else if (EQ (key
, QCembolden
))
270 FcPatternAddBool (pat
, FC_EMBOLDEN
, NILP (val
) ? FcFalse
: FcTrue
);
276 xftfont_open (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
279 Display
*display
= FRAME_X_DISPLAY (f
);
280 Lisp_Object val
, filename
, index
, font_object
;
281 FcPattern
*pat
= NULL
, *match
;
282 struct xftfont_info
*xftfont_info
= NULL
;
285 XftFont
*xftfont
= NULL
;
293 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
297 filename
= XCAR (val
);
299 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
302 pat
= FcPatternCreate ();
303 FcPatternAddInteger (pat
, FC_WEIGHT
, FONT_WEIGHT_NUMERIC (entity
));
304 i
= FONT_SLANT_NUMERIC (entity
) - 100;
306 FcPatternAddInteger (pat
, FC_SLANT
, i
);
307 FcPatternAddInteger (pat
, FC_WIDTH
, FONT_WIDTH_NUMERIC (entity
));
308 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
309 val
= AREF (entity
, FONT_FAMILY_INDEX
);
311 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
312 val
= AREF (entity
, FONT_FOUNDRY_INDEX
);
314 FcPatternAddString (pat
, FC_FOUNDRY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
315 val
= AREF (entity
, FONT_SPACING_INDEX
);
317 FcPatternAddInteger (pat
, FC_SPACING
, XINT (val
));
318 val
= AREF (entity
, FONT_DPI_INDEX
);
321 double dbl
= XINT (val
);
323 FcPatternAddDouble (pat
, FC_DPI
, dbl
);
325 val
= AREF (entity
, FONT_AVGWIDTH_INDEX
);
326 if (INTEGERP (val
) && XINT (val
) == 0)
327 FcPatternAddBool (pat
, FC_SCALABLE
, FcTrue
);
328 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
329 over 10x20-ISO8859-1.pcf.gz). */
330 FcPatternAddCharSet (pat
, FC_CHARSET
, ftfont_get_fc_charset (entity
));
332 xftfont_add_rendering_parameters (pat
, entity
);
334 FcPatternAddString (pat
, FC_FILE
, (FcChar8
*) SDATA (filename
));
335 FcPatternAddInteger (pat
, FC_INDEX
, XINT (index
));
339 /* Make sure that the Xrender extension is added before the Xft one.
340 Otherwise, the close-display hook set by Xft is called after the
341 one for Xrender, and the former tries to re-add the latter. This
342 results in inconsistency of internal states and leads to X
343 protocol error when one reconnects to the same X server.
346 int event_base
, error_base
;
347 XRenderQueryExtension (display
, &event_base
, &error_base
);
350 /* Substitute in values from X resources and XftDefaultSet. */
351 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
352 match
= XftFontMatch (display
, FRAME_X_SCREEN_NUMBER (f
), pat
, &result
);
353 xftfont_fix_match (pat
, match
);
355 FcPatternDestroy (pat
);
356 xftfont
= XftFontOpenPattern (display
, match
);
360 XftPatternDestroy (match
);
363 ft_face
= XftLockFace (xftfont
);
366 /* We should not destroy PAT here because it is kept in XFTFONT and
367 destroyed automatically when XFTFONT is closed. */
368 font_object
= font_make_object (VECSIZE (struct xftfont_info
), entity
, size
);
369 ASET (font_object
, FONT_TYPE_INDEX
, Qxft
);
370 len
= font_unparse_xlfd (entity
, size
, name
, 256);
372 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
373 len
= font_unparse_fcname (entity
, size
, name
, 256);
375 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
377 ASET (font_object
, FONT_FULLNAME_INDEX
,
378 AREF (font_object
, FONT_NAME_INDEX
));
379 ASET (font_object
, FONT_FILE_INDEX
, filename
);
380 ASET (font_object
, FONT_FORMAT_INDEX
,
381 ftfont_font_format (xftfont
->pattern
, filename
));
382 font
= XFONT_OBJECT (font_object
);
383 font
->pixel_size
= pixel_size
;
384 font
->driver
= &xftfont_driver
;
385 font
->encoding_charset
= font
->repertory_charset
= -1;
387 xftfont_info
= (struct xftfont_info
*) font
;
388 xftfont_info
->display
= display
;
389 xftfont_info
->screen
= FRAME_X_SCREEN_NUMBER (f
);
390 xftfont_info
->xftfont
= xftfont
;
391 /* This means that there's no need of transformation. */
392 xftfont_info
->matrix
.xx
= 0;
393 if (FcPatternGetMatrix (xftfont
->pattern
, FC_MATRIX
, 0, &matrix
)
396 xftfont_info
->matrix
.xx
= 0x10000L
* matrix
->xx
;
397 xftfont_info
->matrix
.yy
= 0x10000L
* matrix
->yy
;
398 xftfont_info
->matrix
.xy
= 0x10000L
* matrix
->xy
;
399 xftfont_info
->matrix
.yx
= 0x10000L
* matrix
->yx
;
401 font
->pixel_size
= size
;
402 font
->driver
= &xftfont_driver
;
403 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
404 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
406 spacing
= FC_PROPORTIONAL
;
407 if (! ascii_printable
[0])
410 for (i
= 0; i
< 95; i
++)
411 ascii_printable
[i
] = ' ' + i
;
414 if (spacing
!= FC_PROPORTIONAL
416 && spacing
!= FC_DUAL
420 font
->min_width
= font
->average_width
= font
->space_width
421 = xftfont
->max_advance_width
;
422 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
426 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
427 font
->space_width
= extents
.xOff
;
428 if (font
->space_width
<= 0)
429 /* dirty workaround */
430 font
->space_width
= pixel_size
;
431 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
432 font
->average_width
= (font
->space_width
+ extents
.xOff
) / 95;
436 font
->ascent
= xftfont
->ascent
;
437 font
->descent
= xftfont
->descent
;
440 /* The above condition is a dirty workaround because
441 XftTextExtents8 behaves strangely for some fonts
442 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
443 if (font
->ascent
< extents
.y
)
444 font
->ascent
= extents
.y
;
445 if (font
->descent
< extents
.height
- extents
.y
)
446 font
->descent
= extents
.height
- extents
.y
;
448 font
->height
= font
->ascent
+ font
->descent
;
450 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) == 0)
452 int upEM
= ft_face
->units_per_EM
;
454 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
455 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
456 if (font
->underline_thickness
> 2)
457 font
->underline_position
-= font
->underline_thickness
/ 2;
461 font
->underline_position
= -1;
462 font
->underline_thickness
= 0;
465 xftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
466 xftfont_info
->otf
= NULL
;
467 #endif /* HAVE_LIBOTF */
468 xftfont_info
->ft_size
= ft_face
->size
;
470 /* Unfortunately Xft doesn't provide a way to get minimum char
471 width. So, we use space_width instead. */
472 font
->min_width
= font
->space_width
;
474 font
->baseline_offset
= 0;
475 font
->relative_compose
= 0;
476 font
->default_ascent
= 0;
477 font
->vertical_centering
= 0;
479 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
483 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
484 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
485 font
->baseline_offset
= rec
.u
.integer
;
486 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
487 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
488 font
->relative_compose
= rec
.u
.integer
;
489 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
490 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
491 font
->default_ascent
= rec
.u
.integer
;
499 xftfont_close (FRAME_PTR f
, struct font
*font
)
501 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
504 if (xftfont_info
->otf
)
505 OTF_close (xftfont_info
->otf
);
508 XftUnlockFace (xftfont_info
->xftfont
);
509 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
514 xftfont_prepare_face (FRAME_PTR f
, struct face
*face
)
516 struct xftface_info
*xftface_info
;
519 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
520 if (face
!= face
->ascii_face
)
522 face
->extra
= face
->ascii_face
->extra
;
527 xftface_info
= malloc (sizeof (struct xftface_info
));
530 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
531 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
532 face
->extra
= xftface_info
;
537 xftfont_done_face (FRAME_PTR f
, struct face
*face
)
539 struct xftface_info
*xftface_info
;
542 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
543 if (face
!= face
->ascii_face
548 xftface_info
= (struct xftface_info
*) face
->extra
;
557 xftfont_has_char (Lisp_Object font
, int c
)
559 struct xftfont_info
*xftfont_info
;
560 struct charset
*cs
= NULL
;
562 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
563 && charset_jisx0208
>= 0)
564 cs
= CHARSET_FROM_ID (charset_jisx0208
);
565 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
566 && charset_ksc5601
>= 0)
567 cs
= CHARSET_FROM_ID (charset_ksc5601
);
569 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
571 if (FONT_ENTITY_P (font
))
572 return ftfont_driver
.has_char (font
, c
);
573 xftfont_info
= (struct xftfont_info
*) XFONT_OBJECT (font
);
574 return (XftCharExists (xftfont_info
->display
, xftfont_info
->xftfont
,
575 (FcChar32
) c
) == FcTrue
);
579 xftfont_encode_char (struct font
*font
, int c
)
581 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
582 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
585 return (code
? code
: FONT_INVALID_CODE
);
589 xftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
591 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
595 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
600 metrics
->lbearing
= - extents
.x
;
601 metrics
->rbearing
= - extents
.x
+ extents
.width
;
602 metrics
->width
= extents
.xOff
;
603 metrics
->ascent
= extents
.y
;
604 metrics
->descent
= extents
.height
- extents
.y
;
610 xftfont_get_xft_draw (FRAME_PTR f
)
612 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
617 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
620 FRAME_X_COLORMAP (f
));
624 font_put_frame_data (f
, &xftfont_driver
, xft_draw
);
630 xftfont_draw (struct glyph_string
*s
, int from
, int to
, int x
, int y
, int with_background
)
633 struct face
*face
= s
->face
;
634 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
635 struct xftface_info
*xftface_info
= NULL
;
636 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
642 if (s
->font
== face
->font
)
643 xftface_info
= (struct xftface_info
*) face
->extra
;
644 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
645 &fg
, with_background
? &bg
: NULL
);
647 if (s
->num_clips
> 0)
648 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
650 XftDrawSetClip (xft_draw
, NULL
);
653 XftDrawRect (xft_draw
, &bg
,
654 x
, y
- face
->font
->ascent
, s
->width
, face
->font
->height
);
655 code
= alloca (sizeof (FT_UInt
) * len
);
656 for (i
= 0; i
< len
; i
++)
657 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
658 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
661 for (i
= 0; i
< len
; i
++)
662 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
663 x
+ i
, y
, code
+ i
, 1);
665 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
673 xftfont_shape (Lisp_Object lgstring
)
676 struct xftfont_info
*xftfont_info
;
680 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
681 xftfont_info
= (struct xftfont_info
*) font
;
682 ft_face
= XftLockFace (xftfont_info
->xftfont
);
683 xftfont_info
->ft_size
= ft_face
->size
;
684 val
= ftfont_driver
.shape (lgstring
);
685 XftUnlockFace (xftfont_info
->xftfont
);
690 xftfont_end_for_frame (FRAME_PTR f
)
694 /* Don't do anything if display is dead */
695 if (FRAME_X_DISPLAY (f
) == NULL
) return 0;
697 xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
702 XftDrawDestroy (xft_draw
);
704 font_put_frame_data (f
, &xftfont_driver
, NULL
);
710 xftfont_cached_font_ok (struct frame
*f
, Lisp_Object font_object
, Lisp_Object entity
)
712 struct xftfont_info
*info
= (struct xftfont_info
*) XFONT_OBJECT (font_object
);
713 FcPattern
*oldpat
= info
->xftfont
->pattern
;
714 Display
*display
= FRAME_X_DISPLAY (f
);
715 FcPattern
*pat
= FcPatternCreate ();
717 int ok
= 0, i1
, i2
, r1
, r2
;
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
);
753 syms_of_xftfont (void)
755 DEFSYM (Qxft
, "xft");
756 DEFSYM (QChinting
, ":hinting");
757 DEFSYM (QCautohint
, ":autohint");
758 DEFSYM (QChintstyle
, ":hintstyle");
759 DEFSYM (QCrgba
, ":rgba");
760 DEFSYM (QCembolden
, ":embolden");
761 DEFSYM (QClcdfilter
, ":lcdfilter");
763 xftfont_driver
= ftfont_driver
;
764 xftfont_driver
.type
= Qxft
;
765 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
766 xftfont_driver
.list
= xftfont_list
;
767 xftfont_driver
.match
= xftfont_match
;
768 xftfont_driver
.open
= xftfont_open
;
769 xftfont_driver
.close
= xftfont_close
;
770 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
771 xftfont_driver
.done_face
= xftfont_done_face
;
772 xftfont_driver
.has_char
= xftfont_has_char
;
773 xftfont_driver
.encode_char
= xftfont_encode_char
;
774 xftfont_driver
.text_extents
= xftfont_text_extents
;
775 xftfont_driver
.draw
= xftfont_draw
;
776 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
777 xftfont_driver
.cached_font_ok
= xftfont_cached_font_ok
;
778 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
779 xftfont_driver
.shape
= xftfont_shape
;
782 register_font_driver (&xftfont_driver
, NULL
);