1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 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
P_ ((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 (f
, face
, gc
, xftface_info
, fg
, bg
)
88 struct xftface_info
*xftface_info
;
91 if (xftface_info
&& face
->gc
== gc
)
93 *fg
= xftface_info
->xft_fg
;
95 *bg
= xftface_info
->xft_bg
;
100 int fg_done
= 0, bg_done
= 0;
103 XGetGCValues (FRAME_X_DISPLAY (f
), gc
,
104 GCForeground
| GCBackground
, &xgcv
);
107 if (xgcv
.foreground
== face
->foreground
)
108 *fg
= xftface_info
->xft_fg
, fg_done
= 1;
109 else if (xgcv
.foreground
== face
->background
)
110 *fg
= xftface_info
->xft_bg
, fg_done
= 1;
113 else if (xgcv
.background
== face
->background
)
114 *bg
= xftface_info
->xft_bg
, bg_done
= 1;
115 else if (xgcv
.background
== face
->foreground
)
116 *bg
= xftface_info
->xft_fg
, bg_done
= 1;
119 if (fg_done
+ bg_done
< 2)
123 colors
[0].pixel
= fg
->pixel
= xgcv
.foreground
;
125 colors
[1].pixel
= bg
->pixel
= xgcv
.background
;
126 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
,
128 fg
->color
.alpha
= 0xFFFF;
129 fg
->color
.red
= colors
[0].red
;
130 fg
->color
.green
= colors
[0].green
;
131 fg
->color
.blue
= colors
[0].blue
;
134 bg
->color
.alpha
= 0xFFFF;
135 bg
->color
.red
= colors
[1].red
;
136 bg
->color
.green
= colors
[1].green
;
137 bg
->color
.blue
= colors
[1].blue
;
145 static Lisp_Object xftfont_list
P_ ((Lisp_Object
, Lisp_Object
));
146 static Lisp_Object xftfont_match
P_ ((Lisp_Object
, Lisp_Object
));
147 static Lisp_Object xftfont_open
P_ ((FRAME_PTR
, Lisp_Object
, int));
148 static void xftfont_close
P_ ((FRAME_PTR
, struct font
*));
149 static int xftfont_prepare_face
P_ ((FRAME_PTR
, struct face
*));
150 static void xftfont_done_face
P_ ((FRAME_PTR
, struct face
*));
151 static int xftfont_has_char
P_ ((Lisp_Object
, int));
152 static unsigned xftfont_encode_char
P_ ((struct font
*, int));
153 static int xftfont_text_extents
P_ ((struct font
*, unsigned *, int,
154 struct font_metrics
*));
155 static int xftfont_draw
P_ ((struct glyph_string
*, int, int, int, int, int));
156 static int xftfont_end_for_frame
P_ ((FRAME_PTR f
));
158 struct font_driver xftfont_driver
;
161 xftfont_list (frame
, spec
)
165 Lisp_Object list
= ftfont_driver
.list (frame
, spec
), tail
;
167 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
168 ASET (XCAR (tail
), FONT_TYPE_INDEX
, Qxft
);
173 xftfont_match (frame
, spec
)
177 Lisp_Object entity
= ftfont_driver
.match (frame
, spec
);
180 ASET (entity
, FONT_TYPE_INDEX
, Qxft
);
184 extern Lisp_Object ftfont_font_format
P_ ((FcPattern
*, Lisp_Object
));
185 extern FcCharSet
*ftfont_get_fc_charset
P_ ((Lisp_Object
));
186 extern Lisp_Object QCantialias
;
188 static FcChar8 ascii_printable
[95];
191 xftfont_fix_match (pat
, match
)
192 FcPattern
*pat
, *match
;
194 /* These values are not used for matching (except antialias), but for
195 rendering, so make sure they are carried over to the match.
196 We also put antialias here because most fonts are antialiased, so
197 the match will have antialias true. */
203 FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b
);
206 FcPatternDel (match
, FC_ANTIALIAS
);
207 FcPatternAddBool (match
, FC_ANTIALIAS
, FcFalse
);
209 FcPatternGetBool (pat
, FC_HINTING
, 0, &b
);
212 FcPatternDel (match
, FC_HINTING
);
213 FcPatternAddBool (match
, FC_HINTING
, FcFalse
);
215 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i
))
217 FcPatternDel (match
, FC_HINT_STYLE
);
218 FcPatternAddInteger (match
, FC_HINT_STYLE
, i
);
220 #ifndef FC_LCD_FILTER
221 /* Older fontconfig versions don't have FC_LCD_FILTER. */
222 #define FC_LCD_FILTER "lcdfilter"
224 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i
))
226 FcPatternDel (match
, FC_LCD_FILTER
);
227 FcPatternAddInteger (match
, FC_LCD_FILTER
, i
);
229 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_RGBA
, 0, &i
))
231 FcPatternDel (match
, FC_RGBA
);
232 FcPatternAddInteger (match
, FC_RGBA
, i
);
234 if (FcResultMatch
== FcPatternGetDouble (pat
, FC_DPI
, 0, &dpi
))
236 FcPatternDel (match
, FC_DPI
);
237 FcPatternAddDouble (match
, FC_DPI
, dpi
);
242 xftfont_add_rendering_parameters (pat
, entity
)
249 for (tail
= AREF (entity
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
251 Lisp_Object key
= XCAR (XCAR (tail
));
252 Lisp_Object val
= XCDR (XCAR (tail
));
254 if (EQ (key
, QCantialias
))
255 FcPatternAddBool (pat
, FC_ANTIALIAS
, NILP (val
) ? FcFalse
: FcTrue
);
256 else if (EQ (key
, QChinting
))
257 FcPatternAddBool (pat
, FC_HINTING
, NILP (val
) ? FcFalse
: FcTrue
);
258 else if (EQ (key
, QCautohint
))
259 FcPatternAddBool (pat
, FC_AUTOHINT
, NILP (val
) ? FcFalse
: FcTrue
);
260 else if (EQ (key
, QChintstyle
))
263 FcPatternAddInteger (pat
, FC_HINT_STYLE
, XINT (val
));
264 else if (SYMBOLP (val
)
265 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
266 FcPatternAddInteger (pat
, FC_HINT_STYLE
, ival
);
268 else if (EQ (key
, QCrgba
))
271 FcPatternAddInteger (pat
, FC_RGBA
, XINT (val
));
272 else if (SYMBOLP (val
)
273 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
274 FcPatternAddInteger (pat
, FC_RGBA
, ival
);
276 else if (EQ (key
, QClcdfilter
))
279 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
= XINT (val
));
280 else if (SYMBOLP (val
)
281 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
282 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
);
285 else if (EQ (key
, QCembolden
))
286 FcPatternAddBool (pat
, FC_EMBOLDEN
, NILP (val
) ? FcFalse
: FcTrue
);
292 xftfont_open (f
, entity
, pixel_size
)
298 Display
*display
= FRAME_X_DISPLAY (f
);
299 Lisp_Object val
, filename
, index
, font_object
;
300 FcPattern
*pat
= NULL
, *match
;
301 struct xftfont_info
*xftfont_info
= NULL
;
304 XftFont
*xftfont
= NULL
;
312 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
316 filename
= XCAR (val
);
318 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
321 pat
= FcPatternCreate ();
322 FcPatternAddInteger (pat
, FC_WEIGHT
, FONT_WEIGHT_NUMERIC (entity
));
323 i
= FONT_SLANT_NUMERIC (entity
) - 100;
325 FcPatternAddInteger (pat
, FC_SLANT
, i
);
326 FcPatternAddInteger (pat
, FC_WIDTH
, FONT_WIDTH_NUMERIC (entity
));
327 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
328 val
= AREF (entity
, FONT_FAMILY_INDEX
);
330 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
331 val
= AREF (entity
, FONT_FOUNDRY_INDEX
);
333 FcPatternAddString (pat
, FC_FOUNDRY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
334 val
= AREF (entity
, FONT_SPACING_INDEX
);
336 FcPatternAddInteger (pat
, FC_SPACING
, XINT (val
));
337 val
= AREF (entity
, FONT_DPI_INDEX
);
340 double dbl
= XINT (val
);
342 FcPatternAddDouble (pat
, FC_DPI
, dbl
);
344 val
= AREF (entity
, FONT_AVGWIDTH_INDEX
);
345 if (INTEGERP (val
) && XINT (val
) == 0)
346 FcPatternAddBool (pat
, FC_SCALABLE
, FcTrue
);
347 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
348 over 10x20-ISO8859-1.pcf.gz). */
349 FcPatternAddCharSet (pat
, FC_CHARSET
, ftfont_get_fc_charset (entity
));
351 xftfont_add_rendering_parameters (pat
, entity
);
353 FcPatternAddString (pat
, FC_FILE
, (FcChar8
*) SDATA (filename
));
354 FcPatternAddInteger (pat
, FC_INDEX
, XINT (index
));
358 /* Make sure that the Xrender extension is added before the Xft one.
359 Otherwise, the close-display hook set by Xft is called after the
360 one for Xrender, and the former tries to re-add the latter. This
361 results in inconsistency of internal states and leads to X
362 protocol error when one reconnects to the same X server.
365 int event_base
, error_base
;
366 XRenderQueryExtension (display
, &event_base
, &error_base
);
369 /* Substitute in values from X resources and XftDefaultSet. */
370 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
371 match
= XftFontMatch (display
, FRAME_X_SCREEN_NUMBER (f
), pat
, &result
);
372 xftfont_fix_match (pat
, match
);
374 FcPatternDestroy (pat
);
375 xftfont
= XftFontOpenPattern (display
, match
);
379 XftPatternDestroy (match
);
382 ft_face
= XftLockFace (xftfont
);
385 /* We should not destroy PAT here because it is kept in XFTFONT and
386 destroyed automatically when XFTFONT is closed. */
387 font_object
= font_make_object (VECSIZE (struct xftfont_info
), entity
, size
);
388 ASET (font_object
, FONT_TYPE_INDEX
, Qxft
);
389 len
= font_unparse_xlfd (entity
, size
, name
, 256);
391 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
392 len
= font_unparse_fcname (entity
, size
, name
, 256);
394 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
396 ASET (font_object
, FONT_FULLNAME_INDEX
,
397 AREF (font_object
, FONT_NAME_INDEX
));
398 ASET (font_object
, FONT_FILE_INDEX
, filename
);
399 ASET (font_object
, FONT_FORMAT_INDEX
,
400 ftfont_font_format (xftfont
->pattern
, filename
));
401 font
= XFONT_OBJECT (font_object
);
402 font
->pixel_size
= pixel_size
;
403 font
->driver
= &xftfont_driver
;
404 font
->encoding_charset
= font
->repertory_charset
= -1;
406 xftfont_info
= (struct xftfont_info
*) font
;
407 xftfont_info
->display
= display
;
408 xftfont_info
->screen
= FRAME_X_SCREEN_NUMBER (f
);
409 xftfont_info
->xftfont
= xftfont
;
410 /* This means that there's no need of transformation. */
411 xftfont_info
->matrix
.xx
= 0;
412 if (FcPatternGetMatrix (xftfont
->pattern
, FC_MATRIX
, 0, &matrix
)
415 xftfont_info
->matrix
.xx
= 0x10000L
* matrix
->xx
;
416 xftfont_info
->matrix
.yy
= 0x10000L
* matrix
->yy
;
417 xftfont_info
->matrix
.xy
= 0x10000L
* matrix
->xy
;
418 xftfont_info
->matrix
.yx
= 0x10000L
* matrix
->yx
;
420 font
->pixel_size
= size
;
421 font
->driver
= &xftfont_driver
;
422 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
423 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
425 spacing
= FC_PROPORTIONAL
;
426 if (! ascii_printable
[0])
429 for (i
= 0; i
< 95; i
++)
430 ascii_printable
[i
] = ' ' + i
;
433 if (spacing
!= FC_PROPORTIONAL
&& spacing
!= FC_DUAL
)
435 font
->min_width
= font
->average_width
= font
->space_width
436 = xftfont
->max_advance_width
;
437 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
441 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
442 font
->space_width
= extents
.xOff
;
443 if (font
->space_width
<= 0)
444 /* dirty workaround */
445 font
->space_width
= pixel_size
;
446 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
447 font
->average_width
= (font
->space_width
+ extents
.xOff
) / 95;
451 font
->ascent
= xftfont
->ascent
;
452 font
->descent
= xftfont
->descent
;
455 /* The above condition is a dirty workaround because
456 XftTextExtents8 behaves strangely for some fonts
457 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
458 if (font
->ascent
< extents
.y
)
459 font
->ascent
= extents
.y
;
460 if (font
->descent
< extents
.height
- extents
.y
)
461 font
->descent
= extents
.height
- extents
.y
;
463 font
->height
= font
->ascent
+ font
->descent
;
465 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) == 0)
467 int upEM
= ft_face
->units_per_EM
;
469 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
470 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
471 if (font
->underline_thickness
> 2)
472 font
->underline_position
-= font
->underline_thickness
/ 2;
476 font
->underline_position
= -1;
477 font
->underline_thickness
= 0;
480 xftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
481 xftfont_info
->otf
= NULL
;
482 #endif /* HAVE_LIBOTF */
483 xftfont_info
->ft_size
= ft_face
->size
;
485 /* Unfortunately Xft doesn't provide a way to get minimum char
486 width. So, we use space_width instead. */
487 font
->min_width
= font
->space_width
;
489 font
->baseline_offset
= 0;
490 font
->relative_compose
= 0;
491 font
->default_ascent
= 0;
492 font
->vertical_centering
= 0;
494 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
498 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
499 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
500 font
->baseline_offset
= rec
.u
.integer
;
501 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
502 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
503 font
->relative_compose
= rec
.u
.integer
;
504 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
505 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
506 font
->default_ascent
= rec
.u
.integer
;
514 xftfont_close (f
, font
)
518 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
521 if (xftfont_info
->otf
)
522 OTF_close (xftfont_info
->otf
);
525 XftUnlockFace (xftfont_info
->xftfont
);
526 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
531 xftfont_prepare_face (f
, face
)
535 struct xftface_info
*xftface_info
;
538 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
539 if (face
!= face
->ascii_face
)
541 face
->extra
= face
->ascii_face
->extra
;
546 xftface_info
= malloc (sizeof (struct xftface_info
));
549 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
550 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
551 face
->extra
= xftface_info
;
556 xftfont_done_face (f
, face
)
560 struct xftface_info
*xftface_info
;
563 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
564 if (face
!= face
->ascii_face
569 xftface_info
= (struct xftface_info
*) face
->extra
;
577 extern Lisp_Object Qja
, Qko
;
580 xftfont_has_char (font
, c
)
584 struct xftfont_info
*xftfont_info
;
585 struct charset
*cs
= NULL
;
587 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
588 && charset_jisx0208
>= 0)
589 cs
= CHARSET_FROM_ID (charset_jisx0208
);
590 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
591 && charset_ksc5601
>= 0)
592 cs
= CHARSET_FROM_ID (charset_ksc5601
);
594 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
596 if (FONT_ENTITY_P (font
))
597 return ftfont_driver
.has_char (font
, c
);
598 xftfont_info
= (struct xftfont_info
*) XFONT_OBJECT (font
);
599 return (XftCharExists (xftfont_info
->display
, xftfont_info
->xftfont
,
600 (FcChar32
) c
) == FcTrue
);
604 xftfont_encode_char (font
, c
)
608 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
609 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
612 return (code
? code
: FONT_INVALID_CODE
);
616 xftfont_text_extents (font
, code
, nglyphs
, metrics
)
620 struct font_metrics
*metrics
;
622 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
626 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
631 metrics
->lbearing
= - extents
.x
;
632 metrics
->rbearing
= - extents
.x
+ extents
.width
;
633 metrics
->width
= extents
.xOff
;
634 metrics
->ascent
= extents
.y
;
635 metrics
->descent
= extents
.height
- extents
.y
;
641 xftfont_get_xft_draw (f
)
644 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
649 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
652 FRAME_X_COLORMAP (f
));
656 font_put_frame_data (f
, &xftfont_driver
, xft_draw
);
662 xftfont_draw (s
, from
, to
, x
, y
, with_background
)
663 struct glyph_string
*s
;
664 int from
, to
, x
, y
, with_background
;
667 struct face
*face
= s
->face
;
668 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
669 struct xftface_info
*xftface_info
= NULL
;
670 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
676 if (s
->font
== face
->font
)
677 xftface_info
= (struct xftface_info
*) face
->extra
;
678 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
679 &fg
, with_background
? &bg
: NULL
);
681 if (s
->num_clips
> 0)
682 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
684 XftDrawSetClip (xft_draw
, NULL
);
687 XftDrawRect (xft_draw
, &bg
,
688 x
, y
- face
->font
->ascent
, s
->width
, face
->font
->height
);
689 code
= alloca (sizeof (FT_UInt
) * len
);
690 for (i
= 0; i
< len
; i
++)
691 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
692 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
695 for (i
= 0; i
< len
; i
++)
696 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
697 x
+ i
, y
, code
+ i
, 1);
699 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
707 xftfont_shape (Lisp_Object lgstring
)
710 struct xftfont_info
*xftfont_info
;
714 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
715 xftfont_info
= (struct xftfont_info
*) font
;
716 ft_face
= XftLockFace (xftfont_info
->xftfont
);
717 xftfont_info
->ft_size
= ft_face
->size
;
718 val
= ftfont_driver
.shape (lgstring
);
719 XftUnlockFace (xftfont_info
->xftfont
);
724 xftfont_end_for_frame (f
)
729 /* Don't do anything if display is dead */
730 if (FRAME_X_DISPLAY (f
) == NULL
) return 0;
732 xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
737 XftDrawDestroy (xft_draw
);
739 font_put_frame_data (f
, &xftfont_driver
, NULL
);
745 xftfont_cached_font_ok (f
, font_object
, entity
)
747 Lisp_Object font_object
;
751 struct xftfont_info
*info
= (struct xftfont_info
*) XFONT_OBJECT (font_object
);
752 FcPattern
*oldpat
= info
->xftfont
->pattern
;
753 Display
*display
= FRAME_X_DISPLAY (f
);
754 FcPattern
*pat
= FcPatternCreate ();
756 int ok
= 0, i1
, i2
, r1
, r2
;
758 xftfont_add_rendering_parameters (pat
, entity
);
759 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
761 r1
= FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b1
);
762 r2
= FcPatternGetBool (oldpat
, FC_ANTIALIAS
, 0, &b2
);
763 if (r1
!= r2
|| b1
!= b2
) goto out
;
764 r1
= FcPatternGetBool (pat
, FC_HINTING
, 0, &b1
);
765 r2
= FcPatternGetBool (oldpat
, FC_HINTING
, 0, &b2
);
766 if (r1
!= r2
|| b1
!= b2
) goto out
;
767 r1
= FcPatternGetBool (pat
, FC_AUTOHINT
, 0, &b1
);
768 r2
= FcPatternGetBool (oldpat
, FC_AUTOHINT
, 0, &b2
);
769 if (r1
!= r2
|| b1
!= b2
) goto out
;
771 r1
= FcPatternGetBool (pat
, FC_EMBOLDEN
, 0, &b1
);
772 r2
= FcPatternGetBool (oldpat
, FC_EMBOLDEN
, 0, &b2
);
773 if (r1
!= r2
|| b1
!= b2
) goto out
;
775 r1
= FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i1
);
776 r2
= FcPatternGetInteger (oldpat
, FC_HINT_STYLE
, 0, &i2
);
777 if (r1
!= r2
|| i1
!= i2
) goto out
;
778 r1
= FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i1
);
779 r2
= FcPatternGetInteger (oldpat
, FC_LCD_FILTER
, 0, &i2
);
780 if (r1
!= r2
|| i1
!= i2
) goto out
;
781 r1
= FcPatternGetInteger (pat
, FC_RGBA
, 0, &i1
);
782 r2
= FcPatternGetInteger (oldpat
, FC_RGBA
, 0, &i2
);
783 if (r1
!= r2
|| i1
!= i2
) goto out
;
787 FcPatternDestroy (pat
);
794 DEFSYM (Qxft
, "xft");
795 DEFSYM (QChinting
, ":hinting");
796 DEFSYM (QCautohint
, ":autohint");
797 DEFSYM (QChintstyle
, ":hintstyle");
798 DEFSYM (QCrgba
, ":rgba");
799 DEFSYM (QCembolden
, ":embolden");
800 DEFSYM (QClcdfilter
, ":lcdfilter");
802 xftfont_driver
= ftfont_driver
;
803 xftfont_driver
.type
= Qxft
;
804 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
805 xftfont_driver
.list
= xftfont_list
;
806 xftfont_driver
.match
= xftfont_match
;
807 xftfont_driver
.open
= xftfont_open
;
808 xftfont_driver
.close
= xftfont_close
;
809 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
810 xftfont_driver
.done_face
= xftfont_done_face
;
811 xftfont_driver
.has_char
= xftfont_has_char
;
812 xftfont_driver
.encode_char
= xftfont_encode_char
;
813 xftfont_driver
.text_extents
= xftfont_text_extents
;
814 xftfont_driver
.draw
= xftfont_draw
;
815 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
816 xftfont_driver
.cached_font_ok
= xftfont_cached_font_ok
;
817 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
818 xftfont_driver
.shape
= xftfont_shape
;
821 register_font_driver (&xftfont_driver
, NULL
);
824 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
825 (do not change this comment) */