1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010
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"
39 /* Xft font driver. */
41 static Lisp_Object Qxft
;
42 static Lisp_Object QChinting
, QCautohint
, QChintstyle
, QCrgba
, QCembolden
,
45 /* The actual structure for Xft font that can be casted to struct
51 /* The following five members must be here in this order to be
52 compatible with struct ftfont_info (in ftfont.c). */
54 int maybe_otf
; /* Flag to tell if this may be OTF or not. */
56 #endif /* HAVE_LIBOTF */
65 /* Structure pointed by (struct face *)->extra */
69 XftColor xft_fg
; /* color for face->foreground */
70 XftColor xft_bg
; /* color for face->background */
73 static void xftfont_get_colors
P_ ((FRAME_PTR
, struct face
*, GC gc
,
74 struct xftface_info
*,
75 XftColor
*fg
, XftColor
*bg
));
78 /* Setup foreground and background colors of GC into FG and BG. If
79 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
83 xftfont_get_colors (f
, face
, gc
, xftface_info
, fg
, bg
)
87 struct xftface_info
*xftface_info
;
90 if (xftface_info
&& face
->gc
== gc
)
92 *fg
= xftface_info
->xft_fg
;
94 *bg
= xftface_info
->xft_bg
;
99 int fg_done
= 0, bg_done
= 0;
102 XGetGCValues (FRAME_X_DISPLAY (f
), gc
,
103 GCForeground
| GCBackground
, &xgcv
);
106 if (xgcv
.foreground
== face
->foreground
)
107 *fg
= xftface_info
->xft_fg
, fg_done
= 1;
108 else if (xgcv
.foreground
== face
->background
)
109 *fg
= xftface_info
->xft_bg
, fg_done
= 1;
112 else if (xgcv
.background
== face
->background
)
113 *bg
= xftface_info
->xft_bg
, bg_done
= 1;
114 else if (xgcv
.background
== face
->foreground
)
115 *bg
= xftface_info
->xft_fg
, bg_done
= 1;
118 if (fg_done
+ bg_done
< 2)
122 colors
[0].pixel
= fg
->pixel
= xgcv
.foreground
;
124 colors
[1].pixel
= bg
->pixel
= xgcv
.background
;
125 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
,
127 fg
->color
.alpha
= 0xFFFF;
128 fg
->color
.red
= colors
[0].red
;
129 fg
->color
.green
= colors
[0].green
;
130 fg
->color
.blue
= colors
[0].blue
;
133 bg
->color
.alpha
= 0xFFFF;
134 bg
->color
.red
= colors
[1].red
;
135 bg
->color
.green
= colors
[1].green
;
136 bg
->color
.blue
= colors
[1].blue
;
144 static Lisp_Object xftfont_list
P_ ((Lisp_Object
, Lisp_Object
));
145 static Lisp_Object xftfont_match
P_ ((Lisp_Object
, Lisp_Object
));
146 static Lisp_Object xftfont_open
P_ ((FRAME_PTR
, Lisp_Object
, int));
147 static void xftfont_close
P_ ((FRAME_PTR
, struct font
*));
148 static int xftfont_prepare_face
P_ ((FRAME_PTR
, struct face
*));
149 static void xftfont_done_face
P_ ((FRAME_PTR
, struct face
*));
150 static int xftfont_has_char
P_ ((Lisp_Object
, int));
151 static unsigned xftfont_encode_char
P_ ((struct font
*, int));
152 static int xftfont_text_extents
P_ ((struct font
*, unsigned *, int,
153 struct font_metrics
*));
154 static int xftfont_draw
P_ ((struct glyph_string
*, int, int, int, int, int));
155 static int xftfont_end_for_frame
P_ ((FRAME_PTR f
));
157 struct font_driver xftfont_driver
;
160 xftfont_list (frame
, spec
)
164 Lisp_Object list
= ftfont_driver
.list (frame
, spec
), tail
;
166 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
167 ASET (XCAR (tail
), FONT_TYPE_INDEX
, Qxft
);
172 xftfont_match (frame
, spec
)
176 Lisp_Object entity
= ftfont_driver
.match (frame
, spec
);
179 ASET (entity
, FONT_TYPE_INDEX
, Qxft
);
183 extern Lisp_Object ftfont_font_format
P_ ((FcPattern
*, Lisp_Object
));
184 extern FcCharSet
*ftfont_get_fc_charset
P_ ((Lisp_Object
));
185 extern Lisp_Object QCantialias
;
187 static FcChar8 ascii_printable
[95];
190 xftfont_fix_match (pat
, match
)
191 FcPattern
*pat
, *match
;
193 /* These values are not used for matching (except antialias), but for
194 rendering, so make sure they are carried over to the match.
195 We also put antialias here because most fonts are antialiased, so
196 the match will have antialias true. */
202 FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b
);
205 FcPatternDel (match
, FC_ANTIALIAS
);
206 FcPatternAddBool (match
, FC_ANTIALIAS
, FcFalse
);
208 FcPatternGetBool (pat
, FC_HINTING
, 0, &b
);
211 FcPatternDel (match
, FC_HINTING
);
212 FcPatternAddBool (match
, FC_HINTING
, FcFalse
);
214 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i
))
216 FcPatternDel (match
, FC_HINT_STYLE
);
217 FcPatternAddInteger (match
, FC_HINT_STYLE
, i
);
219 #ifndef FC_LCD_FILTER
220 /* Older fontconfig versions don't have FC_LCD_FILTER. */
221 #define FC_LCD_FILTER "lcdfilter"
223 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i
))
225 FcPatternDel (match
, FC_LCD_FILTER
);
226 FcPatternAddInteger (match
, FC_LCD_FILTER
, i
);
228 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_RGBA
, 0, &i
))
230 FcPatternDel (match
, FC_RGBA
);
231 FcPatternAddInteger (match
, FC_RGBA
, i
);
233 if (FcResultMatch
== FcPatternGetDouble (pat
, FC_DPI
, 0, &dpi
))
235 FcPatternDel (match
, FC_DPI
);
236 FcPatternAddDouble (match
, FC_DPI
, dpi
);
241 xftfont_add_rendering_parameters (pat
, entity
)
248 for (tail
= AREF (entity
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
250 Lisp_Object key
= XCAR (XCAR (tail
));
251 Lisp_Object val
= XCDR (XCAR (tail
));
253 if (EQ (key
, QCantialias
))
254 FcPatternAddBool (pat
, FC_ANTIALIAS
, NILP (val
) ? FcFalse
: FcTrue
);
255 else if (EQ (key
, QChinting
))
256 FcPatternAddBool (pat
, FC_HINTING
, NILP (val
) ? FcFalse
: FcTrue
);
257 else if (EQ (key
, QCautohint
))
258 FcPatternAddBool (pat
, FC_AUTOHINT
, NILP (val
) ? FcFalse
: FcTrue
);
259 else if (EQ (key
, QChintstyle
))
262 FcPatternAddInteger (pat
, FC_HINT_STYLE
, XINT (val
));
263 else if (SYMBOLP (val
)
264 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
265 FcPatternAddInteger (pat
, FC_HINT_STYLE
, ival
);
267 else if (EQ (key
, QCrgba
))
270 FcPatternAddInteger (pat
, FC_RGBA
, XINT (val
));
271 else if (SYMBOLP (val
)
272 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
273 FcPatternAddInteger (pat
, FC_RGBA
, ival
);
275 else if (EQ (key
, QClcdfilter
))
278 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
= XINT (val
));
279 else if (SYMBOLP (val
)
280 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
281 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
);
284 else if (EQ (key
, QCembolden
))
285 FcPatternAddBool (pat
, FC_EMBOLDEN
, NILP (val
) ? FcFalse
: FcTrue
);
291 xftfont_open (f
, entity
, pixel_size
)
297 Display
*display
= FRAME_X_DISPLAY (f
);
298 Lisp_Object val
, filename
, index
, font_object
;
299 FcPattern
*pat
= NULL
, *match
;
300 struct xftfont_info
*xftfont_info
= NULL
;
303 XftFont
*xftfont
= NULL
;
311 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
315 filename
= XCAR (val
);
317 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
320 pat
= FcPatternCreate ();
321 FcPatternAddInteger (pat
, FC_WEIGHT
, FONT_WEIGHT_NUMERIC (entity
));
322 i
= FONT_SLANT_NUMERIC (entity
) - 100;
324 FcPatternAddInteger (pat
, FC_SLANT
, i
);
325 FcPatternAddInteger (pat
, FC_WIDTH
, FONT_WIDTH_NUMERIC (entity
));
326 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
327 val
= AREF (entity
, FONT_FAMILY_INDEX
);
329 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
330 val
= AREF (entity
, FONT_FOUNDRY_INDEX
);
332 FcPatternAddString (pat
, FC_FOUNDRY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
333 val
= AREF (entity
, FONT_SPACING_INDEX
);
335 FcPatternAddInteger (pat
, FC_SPACING
, XINT (val
));
336 val
= AREF (entity
, FONT_DPI_INDEX
);
339 double dbl
= XINT (val
);
341 FcPatternAddDouble (pat
, FC_DPI
, dbl
);
343 val
= AREF (entity
, FONT_AVGWIDTH_INDEX
);
344 if (INTEGERP (val
) && XINT (val
) == 0)
345 FcPatternAddBool (pat
, FC_SCALABLE
, FcTrue
);
346 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
347 over 10x20-ISO8859-1.pcf.gz). */
348 FcPatternAddCharSet (pat
, FC_CHARSET
, ftfont_get_fc_charset (entity
));
350 xftfont_add_rendering_parameters (pat
, entity
);
352 FcPatternAddString (pat
, FC_FILE
, (FcChar8
*) SDATA (filename
));
353 FcPatternAddInteger (pat
, FC_INDEX
, XINT (index
));
357 /* Make sure that the Xrender extension is added before the Xft one.
358 Otherwise, the close-display hook set by Xft is called after the
359 one for Xrender, and the former tries to re-add the latter. This
360 results in inconsistency of internal states and leads to X
361 protocol error when one reconnects to the same X server.
364 int event_base
, error_base
;
365 XRenderQueryExtension (display
, &event_base
, &error_base
);
368 /* Substitute in values from X resources and XftDefaultSet. */
369 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
370 match
= XftFontMatch (display
, FRAME_X_SCREEN_NUMBER (f
), pat
, &result
);
371 xftfont_fix_match (pat
, match
);
373 FcPatternDestroy (pat
);
374 xftfont
= XftFontOpenPattern (display
, match
);
378 XftPatternDestroy (match
);
381 ft_face
= XftLockFace (xftfont
);
384 /* We should not destroy PAT here because it is kept in XFTFONT and
385 destroyed automatically when XFTFONT is closed. */
386 font_object
= font_make_object (VECSIZE (struct xftfont_info
), entity
, size
);
387 ASET (font_object
, FONT_TYPE_INDEX
, Qxft
);
388 len
= font_unparse_xlfd (entity
, size
, name
, 256);
390 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
391 len
= font_unparse_fcname (entity
, size
, name
, 256);
393 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
395 ASET (font_object
, FONT_FULLNAME_INDEX
,
396 AREF (font_object
, FONT_NAME_INDEX
));
397 ASET (font_object
, FONT_FILE_INDEX
, filename
);
398 ASET (font_object
, FONT_FORMAT_INDEX
,
399 ftfont_font_format (xftfont
->pattern
, filename
));
400 font
= XFONT_OBJECT (font_object
);
401 font
->pixel_size
= pixel_size
;
402 font
->driver
= &xftfont_driver
;
403 font
->encoding_charset
= font
->repertory_charset
= -1;
405 xftfont_info
= (struct xftfont_info
*) font
;
406 xftfont_info
->display
= display
;
407 xftfont_info
->screen
= FRAME_X_SCREEN_NUMBER (f
);
408 xftfont_info
->xftfont
= xftfont
;
409 /* This means that there's no need of transformation. */
410 xftfont_info
->matrix
.xx
= 0;
411 if (FcPatternGetMatrix (xftfont
->pattern
, FC_MATRIX
, 0, &matrix
)
414 xftfont_info
->matrix
.xx
= 0x10000L
* matrix
->xx
;
415 xftfont_info
->matrix
.yy
= 0x10000L
* matrix
->yy
;
416 xftfont_info
->matrix
.xy
= 0x10000L
* matrix
->xy
;
417 xftfont_info
->matrix
.yx
= 0x10000L
* matrix
->yx
;
419 font
->pixel_size
= size
;
420 font
->driver
= &xftfont_driver
;
421 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
422 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
424 spacing
= FC_PROPORTIONAL
;
425 if (! ascii_printable
[0])
428 for (i
= 0; i
< 95; i
++)
429 ascii_printable
[i
] = ' ' + i
;
432 if (spacing
!= FC_PROPORTIONAL
)
434 font
->min_width
= font
->average_width
= font
->space_width
435 = xftfont
->max_advance_width
;
436 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
440 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
441 font
->space_width
= extents
.xOff
;
442 if (font
->space_width
<= 0)
443 /* dirty workaround */
444 font
->space_width
= pixel_size
;
445 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
446 font
->average_width
= (font
->space_width
+ extents
.xOff
) / 95;
450 font
->ascent
= xftfont
->ascent
;
451 font
->descent
= xftfont
->descent
;
454 /* The above condition is a dirty workaround because
455 XftTextExtents8 behaves strangely for some fonts
456 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
457 if (font
->ascent
< extents
.y
)
458 font
->ascent
= extents
.y
;
459 if (font
->descent
< extents
.height
- extents
.y
)
460 font
->descent
= extents
.height
- extents
.y
;
462 font
->height
= font
->ascent
+ font
->descent
;
464 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) == 0)
466 int upEM
= ft_face
->units_per_EM
;
468 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
469 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
470 if (font
->underline_thickness
> 2)
471 font
->underline_position
-= font
->underline_thickness
/ 2;
475 font
->underline_position
= -1;
476 font
->underline_thickness
= 0;
479 xftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
480 xftfont_info
->otf
= NULL
;
481 #endif /* HAVE_LIBOTF */
482 xftfont_info
->ft_size
= ft_face
->size
;
484 /* Unfortunately Xft doesn't provide a way to get minimum char
485 width. So, we use space_width instead. */
486 font
->min_width
= font
->space_width
;
488 font
->baseline_offset
= 0;
489 font
->relative_compose
= 0;
490 font
->default_ascent
= 0;
491 font
->vertical_centering
= 0;
493 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
497 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
498 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
499 font
->baseline_offset
= rec
.u
.integer
;
500 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
501 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
502 font
->relative_compose
= rec
.u
.integer
;
503 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
504 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
505 font
->default_ascent
= rec
.u
.integer
;
513 xftfont_close (f
, font
)
517 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
520 if (xftfont_info
->otf
)
521 OTF_close (xftfont_info
->otf
);
524 XftUnlockFace (xftfont_info
->xftfont
);
525 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
530 xftfont_prepare_face (f
, face
)
534 struct xftface_info
*xftface_info
;
537 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
538 if (face
!= face
->ascii_face
)
540 face
->extra
= face
->ascii_face
->extra
;
545 xftface_info
= malloc (sizeof (struct xftface_info
));
548 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
549 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
550 face
->extra
= xftface_info
;
555 xftfont_done_face (f
, face
)
559 struct xftface_info
*xftface_info
;
562 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
563 if (face
!= face
->ascii_face
568 xftface_info
= (struct xftface_info
*) face
->extra
;
576 extern Lisp_Object Qja
, Qko
;
579 xftfont_has_char (font
, c
)
583 struct xftfont_info
*xftfont_info
;
584 struct charset
*cs
= NULL
;
586 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
587 && charset_jisx0208
>= 0)
588 cs
= CHARSET_FROM_ID (charset_jisx0208
);
589 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
590 && charset_ksc5601
>= 0)
591 cs
= CHARSET_FROM_ID (charset_ksc5601
);
593 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
595 if (FONT_ENTITY_P (font
))
596 return ftfont_driver
.has_char (font
, c
);
597 xftfont_info
= (struct xftfont_info
*) XFONT_OBJECT (font
);
598 return (XftCharExists (xftfont_info
->display
, xftfont_info
->xftfont
,
599 (FcChar32
) c
) == FcTrue
);
603 xftfont_encode_char (font
, c
)
607 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
608 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
611 return (code
? code
: FONT_INVALID_CODE
);
615 xftfont_text_extents (font
, code
, nglyphs
, metrics
)
619 struct font_metrics
*metrics
;
621 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
625 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
630 metrics
->lbearing
= - extents
.x
;
631 metrics
->rbearing
= - extents
.x
+ extents
.width
;
632 metrics
->width
= extents
.xOff
;
633 metrics
->ascent
= extents
.y
;
634 metrics
->descent
= extents
.height
- extents
.y
;
640 xftfont_get_xft_draw (f
)
643 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
648 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
651 FRAME_X_COLORMAP (f
));
655 font_put_frame_data (f
, &xftfont_driver
, xft_draw
);
661 xftfont_draw (s
, from
, to
, x
, y
, with_background
)
662 struct glyph_string
*s
;
663 int from
, to
, x
, y
, with_background
;
666 struct face
*face
= s
->face
;
667 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
668 struct xftface_info
*xftface_info
= NULL
;
669 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
675 if (s
->font
== face
->font
)
676 xftface_info
= (struct xftface_info
*) face
->extra
;
677 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
678 &fg
, with_background
? &bg
: NULL
);
680 if (s
->num_clips
> 0)
681 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
683 XftDrawSetClip (xft_draw
, NULL
);
686 XftDrawRect (xft_draw
, &bg
,
687 x
, y
- face
->font
->ascent
, s
->width
, face
->font
->height
);
688 code
= alloca (sizeof (FT_UInt
) * len
);
689 for (i
= 0; i
< len
; i
++)
690 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
691 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
694 for (i
= 0; i
< len
; i
++)
695 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
696 x
+ i
, y
, code
+ i
, 1);
698 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
706 xftfont_end_for_frame (f
)
711 /* Don't do anything if display is dead */
712 if (FRAME_X_DISPLAY (f
) == NULL
) return 0;
714 xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
719 XftDrawDestroy (xft_draw
);
721 font_put_frame_data (f
, &xftfont_driver
, NULL
);
727 xftfont_cached_font_ok (f
, font_object
, entity
)
729 Lisp_Object font_object
;
733 struct xftfont_info
*info
= (struct xftfont_info
*) XFONT_OBJECT (font_object
);
734 FcPattern
*oldpat
= info
->xftfont
->pattern
;
735 Display
*display
= FRAME_X_DISPLAY (f
);
736 FcPattern
*pat
= FcPatternCreate ();
738 int ok
= 0, i1
, i2
, r1
, r2
;
740 xftfont_add_rendering_parameters (pat
, entity
);
741 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
743 r1
= FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b1
);
744 r2
= FcPatternGetBool (oldpat
, FC_ANTIALIAS
, 0, &b2
);
745 if (r1
!= r2
|| b1
!= b2
) goto out
;
746 r1
= FcPatternGetBool (pat
, FC_HINTING
, 0, &b1
);
747 r2
= FcPatternGetBool (oldpat
, FC_HINTING
, 0, &b2
);
748 if (r1
!= r2
|| b1
!= b2
) goto out
;
749 r1
= FcPatternGetBool (pat
, FC_AUTOHINT
, 0, &b1
);
750 r2
= FcPatternGetBool (oldpat
, FC_AUTOHINT
, 0, &b2
);
751 if (r1
!= r2
|| b1
!= b2
) goto out
;
753 r1
= FcPatternGetBool (pat
, FC_EMBOLDEN
, 0, &b1
);
754 r2
= FcPatternGetBool (oldpat
, FC_EMBOLDEN
, 0, &b2
);
755 if (r1
!= r2
|| b1
!= b2
) goto out
;
757 r1
= FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i1
);
758 r2
= FcPatternGetInteger (oldpat
, FC_HINT_STYLE
, 0, &i2
);
759 if (r1
!= r2
|| i1
!= i2
) goto out
;
760 r1
= FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i1
);
761 r2
= FcPatternGetInteger (oldpat
, FC_LCD_FILTER
, 0, &i2
);
762 if (r1
!= r2
|| i1
!= i2
) goto out
;
763 r1
= FcPatternGetInteger (pat
, FC_RGBA
, 0, &i1
);
764 r2
= FcPatternGetInteger (oldpat
, FC_RGBA
, 0, &i2
);
765 if (r1
!= r2
|| i1
!= i2
) goto out
;
769 FcPatternDestroy (pat
);
776 DEFSYM (Qxft
, "xft");
777 DEFSYM (QChinting
, ":hinting");
778 DEFSYM (QCautohint
, ":autohint");
779 DEFSYM (QChintstyle
, ":hintstyle");
780 DEFSYM (QCrgba
, ":rgba");
781 DEFSYM (QCembolden
, ":embolden");
782 DEFSYM (QClcdfilter
, ":lcdfilter");
784 xftfont_driver
= ftfont_driver
;
785 xftfont_driver
.type
= Qxft
;
786 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
787 xftfont_driver
.list
= xftfont_list
;
788 xftfont_driver
.match
= xftfont_match
;
789 xftfont_driver
.open
= xftfont_open
;
790 xftfont_driver
.close
= xftfont_close
;
791 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
792 xftfont_driver
.done_face
= xftfont_done_face
;
793 xftfont_driver
.has_char
= xftfont_has_char
;
794 xftfont_driver
.encode_char
= xftfont_encode_char
;
795 xftfont_driver
.text_extents
= xftfont_text_extents
;
796 xftfont_driver
.draw
= xftfont_draw
;
797 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
798 xftfont_driver
.cached_font_ok
= xftfont_cached_font_ok
;
800 register_font_driver (&xftfont_driver
, NULL
);
803 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
804 (do not change this comment) */