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
435 && spacing
!= FC_DUAL
439 font
->min_width
= font
->average_width
= font
->space_width
440 = xftfont
->max_advance_width
;
441 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
445 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
446 font
->space_width
= extents
.xOff
;
447 if (font
->space_width
<= 0)
448 /* dirty workaround */
449 font
->space_width
= pixel_size
;
450 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
451 font
->average_width
= (font
->space_width
+ extents
.xOff
) / 95;
455 font
->ascent
= xftfont
->ascent
;
456 font
->descent
= xftfont
->descent
;
459 /* The above condition is a dirty workaround because
460 XftTextExtents8 behaves strangely for some fonts
461 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
462 if (font
->ascent
< extents
.y
)
463 font
->ascent
= extents
.y
;
464 if (font
->descent
< extents
.height
- extents
.y
)
465 font
->descent
= extents
.height
- extents
.y
;
467 font
->height
= font
->ascent
+ font
->descent
;
469 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) == 0)
471 int upEM
= ft_face
->units_per_EM
;
473 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
474 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
475 if (font
->underline_thickness
> 2)
476 font
->underline_position
-= font
->underline_thickness
/ 2;
480 font
->underline_position
= -1;
481 font
->underline_thickness
= 0;
484 xftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
485 xftfont_info
->otf
= NULL
;
486 #endif /* HAVE_LIBOTF */
487 xftfont_info
->ft_size
= ft_face
->size
;
489 /* Unfortunately Xft doesn't provide a way to get minimum char
490 width. So, we use space_width instead. */
491 font
->min_width
= font
->space_width
;
493 font
->baseline_offset
= 0;
494 font
->relative_compose
= 0;
495 font
->default_ascent
= 0;
496 font
->vertical_centering
= 0;
498 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
502 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
503 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
504 font
->baseline_offset
= rec
.u
.integer
;
505 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
506 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
507 font
->relative_compose
= rec
.u
.integer
;
508 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
509 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
510 font
->default_ascent
= rec
.u
.integer
;
518 xftfont_close (f
, font
)
522 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
525 if (xftfont_info
->otf
)
526 OTF_close (xftfont_info
->otf
);
529 XftUnlockFace (xftfont_info
->xftfont
);
530 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
535 xftfont_prepare_face (f
, 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
)
545 face
->extra
= face
->ascii_face
->extra
;
550 xftface_info
= malloc (sizeof (struct xftface_info
));
553 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
554 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
555 face
->extra
= xftface_info
;
560 xftfont_done_face (f
, face
)
564 struct xftface_info
*xftface_info
;
567 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
568 if (face
!= face
->ascii_face
573 xftface_info
= (struct xftface_info
*) face
->extra
;
581 extern Lisp_Object Qja
, Qko
;
584 xftfont_has_char (font
, c
)
588 struct xftfont_info
*xftfont_info
;
589 struct charset
*cs
= NULL
;
591 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
592 && charset_jisx0208
>= 0)
593 cs
= CHARSET_FROM_ID (charset_jisx0208
);
594 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
595 && charset_ksc5601
>= 0)
596 cs
= CHARSET_FROM_ID (charset_ksc5601
);
598 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
600 if (FONT_ENTITY_P (font
))
601 return ftfont_driver
.has_char (font
, c
);
602 xftfont_info
= (struct xftfont_info
*) XFONT_OBJECT (font
);
603 return (XftCharExists (xftfont_info
->display
, xftfont_info
->xftfont
,
604 (FcChar32
) c
) == FcTrue
);
608 xftfont_encode_char (font
, c
)
612 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
613 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
616 return (code
? code
: FONT_INVALID_CODE
);
620 xftfont_text_extents (font
, code
, nglyphs
, metrics
)
624 struct font_metrics
*metrics
;
626 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
630 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
635 metrics
->lbearing
= - extents
.x
;
636 metrics
->rbearing
= - extents
.x
+ extents
.width
;
637 metrics
->width
= extents
.xOff
;
638 metrics
->ascent
= extents
.y
;
639 metrics
->descent
= extents
.height
- extents
.y
;
645 xftfont_get_xft_draw (f
)
648 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
653 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
656 FRAME_X_COLORMAP (f
));
660 font_put_frame_data (f
, &xftfont_driver
, xft_draw
);
666 xftfont_draw (s
, from
, to
, x
, y
, with_background
)
667 struct glyph_string
*s
;
668 int from
, to
, x
, y
, with_background
;
671 struct face
*face
= s
->face
;
672 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
673 struct xftface_info
*xftface_info
= NULL
;
674 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
680 if (s
->font
== face
->font
)
681 xftface_info
= (struct xftface_info
*) face
->extra
;
682 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
683 &fg
, with_background
? &bg
: NULL
);
685 if (s
->num_clips
> 0)
686 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
688 XftDrawSetClip (xft_draw
, NULL
);
691 XftDrawRect (xft_draw
, &bg
,
692 x
, y
- face
->font
->ascent
, s
->width
, face
->font
->height
);
693 code
= alloca (sizeof (FT_UInt
) * len
);
694 for (i
= 0; i
< len
; i
++)
695 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
696 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
699 for (i
= 0; i
< len
; i
++)
700 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
701 x
+ i
, y
, code
+ i
, 1);
703 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
711 xftfont_shape (Lisp_Object lgstring
)
714 struct xftfont_info
*xftfont_info
;
718 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
719 xftfont_info
= (struct xftfont_info
*) font
;
720 ft_face
= XftLockFace (xftfont_info
->xftfont
);
721 xftfont_info
->ft_size
= ft_face
->size
;
722 val
= ftfont_driver
.shape (lgstring
);
723 XftUnlockFace (xftfont_info
->xftfont
);
728 xftfont_end_for_frame (f
)
733 /* Don't do anything if display is dead */
734 if (FRAME_X_DISPLAY (f
) == NULL
) return 0;
736 xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
741 XftDrawDestroy (xft_draw
);
743 font_put_frame_data (f
, &xftfont_driver
, NULL
);
749 xftfont_cached_font_ok (f
, font_object
, entity
)
751 Lisp_Object font_object
;
755 struct xftfont_info
*info
= (struct xftfont_info
*) XFONT_OBJECT (font_object
);
756 FcPattern
*oldpat
= info
->xftfont
->pattern
;
757 Display
*display
= FRAME_X_DISPLAY (f
);
758 FcPattern
*pat
= FcPatternCreate ();
760 int ok
= 0, i1
, i2
, r1
, r2
;
762 xftfont_add_rendering_parameters (pat
, entity
);
763 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
765 r1
= FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b1
);
766 r2
= FcPatternGetBool (oldpat
, FC_ANTIALIAS
, 0, &b2
);
767 if (r1
!= r2
|| b1
!= b2
) goto out
;
768 r1
= FcPatternGetBool (pat
, FC_HINTING
, 0, &b1
);
769 r2
= FcPatternGetBool (oldpat
, FC_HINTING
, 0, &b2
);
770 if (r1
!= r2
|| b1
!= b2
) goto out
;
771 r1
= FcPatternGetBool (pat
, FC_AUTOHINT
, 0, &b1
);
772 r2
= FcPatternGetBool (oldpat
, FC_AUTOHINT
, 0, &b2
);
773 if (r1
!= r2
|| b1
!= b2
) goto out
;
775 r1
= FcPatternGetBool (pat
, FC_EMBOLDEN
, 0, &b1
);
776 r2
= FcPatternGetBool (oldpat
, FC_EMBOLDEN
, 0, &b2
);
777 if (r1
!= r2
|| b1
!= b2
) goto out
;
779 r1
= FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i1
);
780 r2
= FcPatternGetInteger (oldpat
, FC_HINT_STYLE
, 0, &i2
);
781 if (r1
!= r2
|| i1
!= i2
) goto out
;
782 r1
= FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i1
);
783 r2
= FcPatternGetInteger (oldpat
, FC_LCD_FILTER
, 0, &i2
);
784 if (r1
!= r2
|| i1
!= i2
) goto out
;
785 r1
= FcPatternGetInteger (pat
, FC_RGBA
, 0, &i1
);
786 r2
= FcPatternGetInteger (oldpat
, FC_RGBA
, 0, &i2
);
787 if (r1
!= r2
|| i1
!= i2
) goto out
;
791 FcPatternDestroy (pat
);
798 DEFSYM (Qxft
, "xft");
799 DEFSYM (QChinting
, ":hinting");
800 DEFSYM (QCautohint
, ":autohint");
801 DEFSYM (QChintstyle
, ":hintstyle");
802 DEFSYM (QCrgba
, ":rgba");
803 DEFSYM (QCembolden
, ":embolden");
804 DEFSYM (QClcdfilter
, ":lcdfilter");
806 xftfont_driver
= ftfont_driver
;
807 xftfont_driver
.type
= Qxft
;
808 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
809 xftfont_driver
.list
= xftfont_list
;
810 xftfont_driver
.match
= xftfont_match
;
811 xftfont_driver
.open
= xftfont_open
;
812 xftfont_driver
.close
= xftfont_close
;
813 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
814 xftfont_driver
.done_face
= xftfont_done_face
;
815 xftfont_driver
.has_char
= xftfont_has_char
;
816 xftfont_driver
.encode_char
= xftfont_encode_char
;
817 xftfont_driver
.text_extents
= xftfont_text_extents
;
818 xftfont_driver
.draw
= xftfont_draw
;
819 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
820 xftfont_driver
.cached_font_ok
= xftfont_cached_font_ok
;
821 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
822 xftfont_driver
.shape
= xftfont_shape
;
825 register_font_driver (&xftfont_driver
, NULL
);
828 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
829 (do not change this comment) */