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 (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 (FRAME_PTR f
, struct face
*face
, GC gc
, struct xftface_info
*xftface_info
, XftColor
*fg
, XftColor
*bg
)
85 if (xftface_info
&& face
->gc
== gc
)
87 *fg
= xftface_info
->xft_fg
;
89 *bg
= xftface_info
->xft_bg
;
94 int fg_done
= 0, bg_done
= 0;
97 XGetGCValues (FRAME_X_DISPLAY (f
), gc
,
98 GCForeground
| GCBackground
, &xgcv
);
101 if (xgcv
.foreground
== face
->foreground
)
102 *fg
= xftface_info
->xft_fg
, fg_done
= 1;
103 else if (xgcv
.foreground
== face
->background
)
104 *fg
= xftface_info
->xft_bg
, fg_done
= 1;
107 else if (xgcv
.background
== face
->background
)
108 *bg
= xftface_info
->xft_bg
, bg_done
= 1;
109 else if (xgcv
.background
== face
->foreground
)
110 *bg
= xftface_info
->xft_fg
, bg_done
= 1;
113 if (fg_done
+ bg_done
< 2)
117 colors
[0].pixel
= fg
->pixel
= xgcv
.foreground
;
119 colors
[1].pixel
= bg
->pixel
= xgcv
.background
;
120 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
,
122 fg
->color
.alpha
= 0xFFFF;
123 fg
->color
.red
= colors
[0].red
;
124 fg
->color
.green
= colors
[0].green
;
125 fg
->color
.blue
= colors
[0].blue
;
128 bg
->color
.alpha
= 0xFFFF;
129 bg
->color
.red
= colors
[1].red
;
130 bg
->color
.green
= colors
[1].green
;
131 bg
->color
.blue
= colors
[1].blue
;
139 static Lisp_Object
xftfont_list (Lisp_Object
, Lisp_Object
);
140 static Lisp_Object
xftfont_match (Lisp_Object
, Lisp_Object
);
141 static Lisp_Object
xftfont_open (FRAME_PTR
, Lisp_Object
, int);
142 static void xftfont_close (FRAME_PTR
, struct font
*);
143 static int xftfont_prepare_face (FRAME_PTR
, struct face
*);
144 static void xftfont_done_face (FRAME_PTR
, struct face
*);
145 static int xftfont_has_char (Lisp_Object
, int);
146 static unsigned xftfont_encode_char (struct font
*, int);
147 static int xftfont_text_extents (struct font
*, unsigned *, int,
148 struct font_metrics
*);
149 static int xftfont_draw (struct glyph_string
*, int, int, int, int, int);
150 static int xftfont_end_for_frame (FRAME_PTR f
);
152 struct font_driver xftfont_driver
;
155 xftfont_list (Lisp_Object frame
, Lisp_Object spec
)
157 Lisp_Object list
= ftfont_driver
.list (frame
, spec
), tail
;
159 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
160 ASET (XCAR (tail
), FONT_TYPE_INDEX
, Qxft
);
165 xftfont_match (Lisp_Object frame
, Lisp_Object spec
)
167 Lisp_Object entity
= ftfont_driver
.match (frame
, spec
);
170 ASET (entity
, FONT_TYPE_INDEX
, Qxft
);
174 extern Lisp_Object
ftfont_font_format (FcPattern
*, Lisp_Object
);
175 extern FcCharSet
*ftfont_get_fc_charset (Lisp_Object
);
176 extern Lisp_Object QCantialias
;
178 static FcChar8 ascii_printable
[95];
181 xftfont_fix_match (FcPattern
*pat
, FcPattern
*match
)
183 /* These values are not used for matching (except antialias), but for
184 rendering, so make sure they are carried over to the match.
185 We also put antialias here because most fonts are antialiased, so
186 the match will have antialias true. */
192 FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b
);
195 FcPatternDel (match
, FC_ANTIALIAS
);
196 FcPatternAddBool (match
, FC_ANTIALIAS
, FcFalse
);
198 FcPatternGetBool (pat
, FC_HINTING
, 0, &b
);
201 FcPatternDel (match
, FC_HINTING
);
202 FcPatternAddBool (match
, FC_HINTING
, FcFalse
);
204 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i
))
206 FcPatternDel (match
, FC_HINT_STYLE
);
207 FcPatternAddInteger (match
, FC_HINT_STYLE
, i
);
209 #ifndef FC_LCD_FILTER
210 /* Older fontconfig versions don't have FC_LCD_FILTER. */
211 #define FC_LCD_FILTER "lcdfilter"
213 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i
))
215 FcPatternDel (match
, FC_LCD_FILTER
);
216 FcPatternAddInteger (match
, FC_LCD_FILTER
, i
);
218 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_RGBA
, 0, &i
))
220 FcPatternDel (match
, FC_RGBA
);
221 FcPatternAddInteger (match
, FC_RGBA
, i
);
223 if (FcResultMatch
== FcPatternGetDouble (pat
, FC_DPI
, 0, &dpi
))
225 FcPatternDel (match
, FC_DPI
);
226 FcPatternAddDouble (match
, FC_DPI
, dpi
);
231 xftfont_add_rendering_parameters (FcPattern
*pat
, Lisp_Object entity
)
236 for (tail
= AREF (entity
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
238 Lisp_Object key
= XCAR (XCAR (tail
));
239 Lisp_Object val
= XCDR (XCAR (tail
));
241 if (EQ (key
, QCantialias
))
242 FcPatternAddBool (pat
, FC_ANTIALIAS
, NILP (val
) ? FcFalse
: FcTrue
);
243 else if (EQ (key
, QChinting
))
244 FcPatternAddBool (pat
, FC_HINTING
, NILP (val
) ? FcFalse
: FcTrue
);
245 else if (EQ (key
, QCautohint
))
246 FcPatternAddBool (pat
, FC_AUTOHINT
, NILP (val
) ? FcFalse
: FcTrue
);
247 else if (EQ (key
, QChintstyle
))
250 FcPatternAddInteger (pat
, FC_HINT_STYLE
, XINT (val
));
251 else if (SYMBOLP (val
)
252 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
253 FcPatternAddInteger (pat
, FC_HINT_STYLE
, ival
);
255 else if (EQ (key
, QCrgba
))
258 FcPatternAddInteger (pat
, FC_RGBA
, XINT (val
));
259 else if (SYMBOLP (val
)
260 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
261 FcPatternAddInteger (pat
, FC_RGBA
, ival
);
263 else if (EQ (key
, QClcdfilter
))
266 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
= XINT (val
));
267 else if (SYMBOLP (val
)
268 && FcNameConstant (SDATA (SYMBOL_NAME (val
)), &ival
))
269 FcPatternAddInteger (pat
, FC_LCD_FILTER
, ival
);
272 else if (EQ (key
, QCembolden
))
273 FcPatternAddBool (pat
, FC_EMBOLDEN
, NILP (val
) ? FcFalse
: FcTrue
);
279 xftfont_open (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
282 Display
*display
= FRAME_X_DISPLAY (f
);
283 Lisp_Object val
, filename
, index
, font_object
;
284 FcPattern
*pat
= NULL
, *match
;
285 struct xftfont_info
*xftfont_info
= NULL
;
288 XftFont
*xftfont
= NULL
;
296 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
300 filename
= XCAR (val
);
302 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
305 pat
= FcPatternCreate ();
306 FcPatternAddInteger (pat
, FC_WEIGHT
, FONT_WEIGHT_NUMERIC (entity
));
307 i
= FONT_SLANT_NUMERIC (entity
) - 100;
309 FcPatternAddInteger (pat
, FC_SLANT
, i
);
310 FcPatternAddInteger (pat
, FC_WIDTH
, FONT_WIDTH_NUMERIC (entity
));
311 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
312 val
= AREF (entity
, FONT_FAMILY_INDEX
);
314 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
315 val
= AREF (entity
, FONT_FOUNDRY_INDEX
);
317 FcPatternAddString (pat
, FC_FOUNDRY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
318 val
= AREF (entity
, FONT_SPACING_INDEX
);
320 FcPatternAddInteger (pat
, FC_SPACING
, XINT (val
));
321 val
= AREF (entity
, FONT_DPI_INDEX
);
324 double dbl
= XINT (val
);
326 FcPatternAddDouble (pat
, FC_DPI
, dbl
);
328 val
= AREF (entity
, FONT_AVGWIDTH_INDEX
);
329 if (INTEGERP (val
) && XINT (val
) == 0)
330 FcPatternAddBool (pat
, FC_SCALABLE
, FcTrue
);
331 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
332 over 10x20-ISO8859-1.pcf.gz). */
333 FcPatternAddCharSet (pat
, FC_CHARSET
, ftfont_get_fc_charset (entity
));
335 xftfont_add_rendering_parameters (pat
, entity
);
337 FcPatternAddString (pat
, FC_FILE
, (FcChar8
*) SDATA (filename
));
338 FcPatternAddInteger (pat
, FC_INDEX
, XINT (index
));
342 /* Make sure that the Xrender extension is added before the Xft one.
343 Otherwise, the close-display hook set by Xft is called after the
344 one for Xrender, and the former tries to re-add the latter. This
345 results in inconsistency of internal states and leads to X
346 protocol error when one reconnects to the same X server.
349 int event_base
, error_base
;
350 XRenderQueryExtension (display
, &event_base
, &error_base
);
353 /* Substitute in values from X resources and XftDefaultSet. */
354 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
355 match
= XftFontMatch (display
, FRAME_X_SCREEN_NUMBER (f
), pat
, &result
);
356 xftfont_fix_match (pat
, match
);
358 FcPatternDestroy (pat
);
359 xftfont
= XftFontOpenPattern (display
, match
);
363 XftPatternDestroy (match
);
366 ft_face
= XftLockFace (xftfont
);
369 /* We should not destroy PAT here because it is kept in XFTFONT and
370 destroyed automatically when XFTFONT is closed. */
371 font_object
= font_make_object (VECSIZE (struct xftfont_info
), entity
, size
);
372 ASET (font_object
, FONT_TYPE_INDEX
, Qxft
);
373 len
= font_unparse_xlfd (entity
, size
, name
, 256);
375 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
376 len
= font_unparse_fcname (entity
, size
, name
, 256);
378 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
380 ASET (font_object
, FONT_FULLNAME_INDEX
,
381 AREF (font_object
, FONT_NAME_INDEX
));
382 ASET (font_object
, FONT_FILE_INDEX
, filename
);
383 ASET (font_object
, FONT_FORMAT_INDEX
,
384 ftfont_font_format (xftfont
->pattern
, filename
));
385 font
= XFONT_OBJECT (font_object
);
386 font
->pixel_size
= pixel_size
;
387 font
->driver
= &xftfont_driver
;
388 font
->encoding_charset
= font
->repertory_charset
= -1;
390 xftfont_info
= (struct xftfont_info
*) font
;
391 xftfont_info
->display
= display
;
392 xftfont_info
->screen
= FRAME_X_SCREEN_NUMBER (f
);
393 xftfont_info
->xftfont
= xftfont
;
394 /* This means that there's no need of transformation. */
395 xftfont_info
->matrix
.xx
= 0;
396 if (FcPatternGetMatrix (xftfont
->pattern
, FC_MATRIX
, 0, &matrix
)
399 xftfont_info
->matrix
.xx
= 0x10000L
* matrix
->xx
;
400 xftfont_info
->matrix
.yy
= 0x10000L
* matrix
->yy
;
401 xftfont_info
->matrix
.xy
= 0x10000L
* matrix
->xy
;
402 xftfont_info
->matrix
.yx
= 0x10000L
* matrix
->yx
;
404 font
->pixel_size
= size
;
405 font
->driver
= &xftfont_driver
;
406 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
407 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
409 spacing
= FC_PROPORTIONAL
;
410 if (! ascii_printable
[0])
413 for (i
= 0; i
< 95; i
++)
414 ascii_printable
[i
] = ' ' + i
;
417 if (spacing
!= FC_PROPORTIONAL
&& spacing
!= FC_DUAL
)
419 font
->min_width
= font
->average_width
= font
->space_width
420 = xftfont
->max_advance_width
;
421 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
425 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
426 font
->space_width
= extents
.xOff
;
427 if (font
->space_width
<= 0)
428 /* dirty workaround */
429 font
->space_width
= pixel_size
;
430 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
431 font
->average_width
= (font
->space_width
+ extents
.xOff
) / 95;
435 font
->ascent
= xftfont
->ascent
;
436 font
->descent
= xftfont
->descent
;
439 /* The above condition is a dirty workaround because
440 XftTextExtents8 behaves strangely for some fonts
441 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
442 if (font
->ascent
< extents
.y
)
443 font
->ascent
= extents
.y
;
444 if (font
->descent
< extents
.height
- extents
.y
)
445 font
->descent
= extents
.height
- extents
.y
;
447 font
->height
= font
->ascent
+ font
->descent
;
449 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) == 0)
451 int upEM
= ft_face
->units_per_EM
;
453 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
454 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
455 if (font
->underline_thickness
> 2)
456 font
->underline_position
-= font
->underline_thickness
/ 2;
460 font
->underline_position
= -1;
461 font
->underline_thickness
= 0;
464 xftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
465 xftfont_info
->otf
= NULL
;
466 #endif /* HAVE_LIBOTF */
467 xftfont_info
->ft_size
= ft_face
->size
;
469 /* Unfortunately Xft doesn't provide a way to get minimum char
470 width. So, we use space_width instead. */
471 font
->min_width
= font
->space_width
;
473 font
->baseline_offset
= 0;
474 font
->relative_compose
= 0;
475 font
->default_ascent
= 0;
476 font
->vertical_centering
= 0;
478 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
482 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
483 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
484 font
->baseline_offset
= rec
.u
.integer
;
485 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
486 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
487 font
->relative_compose
= rec
.u
.integer
;
488 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
489 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
490 font
->default_ascent
= rec
.u
.integer
;
498 xftfont_close (FRAME_PTR f
, struct font
*font
)
500 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
503 if (xftfont_info
->otf
)
504 OTF_close (xftfont_info
->otf
);
507 XftUnlockFace (xftfont_info
->xftfont
);
508 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
513 xftfont_prepare_face (FRAME_PTR f
, struct face
*face
)
515 struct xftface_info
*xftface_info
;
518 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
519 if (face
!= face
->ascii_face
)
521 face
->extra
= face
->ascii_face
->extra
;
526 xftface_info
= malloc (sizeof (struct xftface_info
));
529 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
530 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
531 face
->extra
= xftface_info
;
536 xftfont_done_face (FRAME_PTR f
, struct face
*face
)
538 struct xftface_info
*xftface_info
;
541 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
542 if (face
!= face
->ascii_face
547 xftface_info
= (struct xftface_info
*) face
->extra
;
555 extern Lisp_Object Qja
, Qko
;
558 xftfont_has_char (Lisp_Object font
, int c
)
560 struct xftfont_info
*xftfont_info
;
561 struct charset
*cs
= NULL
;
563 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
564 && charset_jisx0208
>= 0)
565 cs
= CHARSET_FROM_ID (charset_jisx0208
);
566 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
567 && charset_ksc5601
>= 0)
568 cs
= CHARSET_FROM_ID (charset_ksc5601
);
570 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
572 if (FONT_ENTITY_P (font
))
573 return ftfont_driver
.has_char (font
, c
);
574 xftfont_info
= (struct xftfont_info
*) XFONT_OBJECT (font
);
575 return (XftCharExists (xftfont_info
->display
, xftfont_info
->xftfont
,
576 (FcChar32
) c
) == FcTrue
);
580 xftfont_encode_char (struct font
*font
, int c
)
582 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
583 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
586 return (code
? code
: FONT_INVALID_CODE
);
590 xftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
592 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
596 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
601 metrics
->lbearing
= - extents
.x
;
602 metrics
->rbearing
= - extents
.x
+ extents
.width
;
603 metrics
->width
= extents
.xOff
;
604 metrics
->ascent
= extents
.y
;
605 metrics
->descent
= extents
.height
- extents
.y
;
611 xftfont_get_xft_draw (FRAME_PTR f
)
613 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
618 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
621 FRAME_X_COLORMAP (f
));
625 font_put_frame_data (f
, &xftfont_driver
, xft_draw
);
631 xftfont_draw (struct glyph_string
*s
, int from
, int to
, int x
, int y
, int with_background
)
634 struct face
*face
= s
->face
;
635 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
636 struct xftface_info
*xftface_info
= NULL
;
637 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
643 if (s
->font
== face
->font
)
644 xftface_info
= (struct xftface_info
*) face
->extra
;
645 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
646 &fg
, with_background
? &bg
: NULL
);
648 if (s
->num_clips
> 0)
649 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
651 XftDrawSetClip (xft_draw
, NULL
);
654 XftDrawRect (xft_draw
, &bg
,
655 x
, y
- face
->font
->ascent
, s
->width
, face
->font
->height
);
656 code
= alloca (sizeof (FT_UInt
) * len
);
657 for (i
= 0; i
< len
; i
++)
658 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
659 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
662 for (i
= 0; i
< len
; i
++)
663 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
664 x
+ i
, y
, code
+ i
, 1);
666 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
674 xftfont_end_for_frame (FRAME_PTR f
)
678 /* Don't do anything if display is dead */
679 if (FRAME_X_DISPLAY (f
) == NULL
) return 0;
681 xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
686 XftDrawDestroy (xft_draw
);
688 font_put_frame_data (f
, &xftfont_driver
, NULL
);
694 xftfont_cached_font_ok (struct frame
*f
, Lisp_Object font_object
, Lisp_Object entity
)
696 struct xftfont_info
*info
= (struct xftfont_info
*) XFONT_OBJECT (font_object
);
697 FcPattern
*oldpat
= info
->xftfont
->pattern
;
698 Display
*display
= FRAME_X_DISPLAY (f
);
699 FcPattern
*pat
= FcPatternCreate ();
701 int ok
= 0, i1
, i2
, r1
, r2
;
703 xftfont_add_rendering_parameters (pat
, entity
);
704 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
706 r1
= FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b1
);
707 r2
= FcPatternGetBool (oldpat
, FC_ANTIALIAS
, 0, &b2
);
708 if (r1
!= r2
|| b1
!= b2
) goto out
;
709 r1
= FcPatternGetBool (pat
, FC_HINTING
, 0, &b1
);
710 r2
= FcPatternGetBool (oldpat
, FC_HINTING
, 0, &b2
);
711 if (r1
!= r2
|| b1
!= b2
) goto out
;
712 r1
= FcPatternGetBool (pat
, FC_AUTOHINT
, 0, &b1
);
713 r2
= FcPatternGetBool (oldpat
, FC_AUTOHINT
, 0, &b2
);
714 if (r1
!= r2
|| b1
!= b2
) goto out
;
716 r1
= FcPatternGetBool (pat
, FC_EMBOLDEN
, 0, &b1
);
717 r2
= FcPatternGetBool (oldpat
, FC_EMBOLDEN
, 0, &b2
);
718 if (r1
!= r2
|| b1
!= b2
) goto out
;
720 r1
= FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i1
);
721 r2
= FcPatternGetInteger (oldpat
, FC_HINT_STYLE
, 0, &i2
);
722 if (r1
!= r2
|| i1
!= i2
) goto out
;
723 r1
= FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i1
);
724 r2
= FcPatternGetInteger (oldpat
, FC_LCD_FILTER
, 0, &i2
);
725 if (r1
!= r2
|| i1
!= i2
) goto out
;
726 r1
= FcPatternGetInteger (pat
, FC_RGBA
, 0, &i1
);
727 r2
= FcPatternGetInteger (oldpat
, FC_RGBA
, 0, &i2
);
728 if (r1
!= r2
|| i1
!= i2
) goto out
;
732 FcPatternDestroy (pat
);
737 syms_of_xftfont (void)
739 DEFSYM (Qxft
, "xft");
740 DEFSYM (QChinting
, ":hinting");
741 DEFSYM (QCautohint
, ":autohint");
742 DEFSYM (QChintstyle
, ":hintstyle");
743 DEFSYM (QCrgba
, ":rgba");
744 DEFSYM (QCembolden
, ":embolden");
745 DEFSYM (QClcdfilter
, ":lcdfilter");
747 xftfont_driver
= ftfont_driver
;
748 xftfont_driver
.type
= Qxft
;
749 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
750 xftfont_driver
.list
= xftfont_list
;
751 xftfont_driver
.match
= xftfont_match
;
752 xftfont_driver
.open
= xftfont_open
;
753 xftfont_driver
.close
= xftfont_close
;
754 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
755 xftfont_driver
.done_face
= xftfont_done_face
;
756 xftfont_driver
.has_char
= xftfont_has_char
;
757 xftfont_driver
.encode_char
= xftfont_encode_char
;
758 xftfont_driver
.text_extents
= xftfont_text_extents
;
759 xftfont_driver
.draw
= xftfont_draw
;
760 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
761 xftfont_driver
.cached_font_ok
= xftfont_cached_font_ok
;
763 register_font_driver (&xftfont_driver
, NULL
);
766 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
767 (do not change this comment) */