1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009
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
;
44 /* The actual structure for Xft font that can be casted to struct
50 /* The following four members must be here in this order to be
51 compatible with struct ftfont_info (in ftfont.c). */
53 int maybe_otf
; /* Flag to tell if this may be OTF or not. */
55 #endif /* HAVE_LIBOTF */
63 /* Structure pointed by (struct face *)->extra */
67 XftColor xft_fg
; /* color for face->foreground */
68 XftColor xft_bg
; /* color for face->background */
71 static void xftfont_get_colors
P_ ((FRAME_PTR
, struct face
*, GC gc
,
72 struct xftface_info
*,
73 XftColor
*fg
, XftColor
*bg
));
76 /* Setup foreground and background colors of GC into FG and BG. If
77 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
81 xftfont_get_colors (f
, face
, gc
, xftface_info
, fg
, bg
)
85 struct xftface_info
*xftface_info
;
88 if (xftface_info
&& face
->gc
== gc
)
90 *fg
= xftface_info
->xft_fg
;
92 *bg
= xftface_info
->xft_bg
;
97 int fg_done
= 0, bg_done
= 0;
100 XGetGCValues (FRAME_X_DISPLAY (f
), gc
,
101 GCForeground
| GCBackground
, &xgcv
);
104 if (xgcv
.foreground
== face
->foreground
)
105 *fg
= xftface_info
->xft_fg
, fg_done
= 1;
106 else if (xgcv
.foreground
== face
->background
)
107 *fg
= xftface_info
->xft_bg
, fg_done
= 1;
110 else if (xgcv
.background
== face
->background
)
111 *bg
= xftface_info
->xft_bg
, bg_done
= 1;
112 else if (xgcv
.background
== face
->foreground
)
113 *bg
= xftface_info
->xft_fg
, bg_done
= 1;
116 if (fg_done
+ bg_done
< 2)
120 colors
[0].pixel
= fg
->pixel
= xgcv
.foreground
;
122 colors
[1].pixel
= bg
->pixel
= xgcv
.background
;
123 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
,
125 fg
->color
.alpha
= 0xFFFF;
126 fg
->color
.red
= colors
[0].red
;
127 fg
->color
.green
= colors
[0].green
;
128 fg
->color
.blue
= colors
[0].blue
;
131 bg
->color
.alpha
= 0xFFFF;
132 bg
->color
.red
= colors
[1].red
;
133 bg
->color
.green
= colors
[1].green
;
134 bg
->color
.blue
= colors
[1].blue
;
142 static Lisp_Object xftfont_list
P_ ((Lisp_Object
, Lisp_Object
));
143 static Lisp_Object xftfont_match
P_ ((Lisp_Object
, Lisp_Object
));
144 static Lisp_Object xftfont_open
P_ ((FRAME_PTR
, Lisp_Object
, int));
145 static void xftfont_close
P_ ((FRAME_PTR
, struct font
*));
146 static int xftfont_prepare_face
P_ ((FRAME_PTR
, struct face
*));
147 static void xftfont_done_face
P_ ((FRAME_PTR
, struct face
*));
148 static int xftfont_has_char
P_ ((Lisp_Object
, int));
149 static unsigned xftfont_encode_char
P_ ((struct font
*, int));
150 static int xftfont_text_extents
P_ ((struct font
*, unsigned *, int,
151 struct font_metrics
*));
152 static int xftfont_draw
P_ ((struct glyph_string
*, int, int, int, int, int));
153 static int xftfont_end_for_frame
P_ ((FRAME_PTR f
));
155 struct font_driver xftfont_driver
;
158 xftfont_list (frame
, spec
)
162 Lisp_Object list
= ftfont_driver
.list (frame
, spec
), tail
;
164 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
165 ASET (XCAR (tail
), FONT_TYPE_INDEX
, Qxft
);
170 xftfont_match (frame
, spec
)
174 Lisp_Object entity
= ftfont_driver
.match (frame
, spec
);
177 ASET (entity
, FONT_TYPE_INDEX
, Qxft
);
181 extern Lisp_Object ftfont_font_format
P_ ((FcPattern
*, Lisp_Object
));
182 extern FcCharSet
*ftfont_get_fc_charset
P_ ((Lisp_Object
));
183 extern Lisp_Object QCantialias
;
185 static FcChar8 ascii_printable
[95];
188 xftfont_fix_match (pat
, match
)
189 FcPattern
*pat
, *match
;
191 /* These values are not used for matching (except antialias), but for
192 rendering, so make sure they are carried over to the match.
193 We also put antialias here because most fonts are antialiased, so
194 the match will have antialias true. */
200 FcPatternGetBool (pat
, FC_ANTIALIAS
, 0, &b
);
203 FcPatternDel (match
, FC_ANTIALIAS
);
204 FcPatternAddBool (match
, FC_ANTIALIAS
, FcFalse
);
206 FcPatternGetBool (pat
, FC_HINTING
, 0, &b
);
209 FcPatternDel (match
, FC_HINTING
);
210 FcPatternAddBool (match
, FC_HINTING
, FcFalse
);
212 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_HINT_STYLE
, 0, &i
))
214 FcPatternDel (match
, FC_HINT_STYLE
);
215 FcPatternAddInteger (match
, FC_HINT_STYLE
, i
);
217 #ifndef FC_LCD_FILTER
218 /* Older fontconfig versions don't have FC_LCD_FILTER. */
219 #define FC_LCD_FILTER "lcdfilter"
221 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i
))
223 FcPatternDel (match
, FC_LCD_FILTER
);
224 FcPatternAddInteger (match
, FC_LCD_FILTER
, i
);
226 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_RGBA
, 0, &i
))
228 FcPatternDel (match
, FC_RGBA
);
229 FcPatternAddInteger (match
, FC_RGBA
, i
);
231 if (FcResultMatch
== FcPatternGetDouble (pat
, FC_DPI
, 0, &dpi
))
233 FcPatternDel (match
, FC_DPI
);
234 FcPatternAddDouble (match
, FC_DPI
, dpi
);
239 xftfont_open (f
, entity
, pixel_size
)
245 Display
*display
= FRAME_X_DISPLAY (f
);
246 Lisp_Object val
, filename
, index
, tail
, font_object
;
247 FcPattern
*pat
= NULL
, *match
;
248 struct xftfont_info
*xftfont_info
= NULL
;
251 XftFont
*xftfont
= NULL
;
258 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
262 filename
= XCAR (val
);
264 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
267 pat
= FcPatternCreate ();
268 FcPatternAddInteger (pat
, FC_WEIGHT
, FONT_WEIGHT_NUMERIC (entity
));
269 i
= FONT_SLANT_NUMERIC (entity
) - 100;
271 FcPatternAddInteger (pat
, FC_SLANT
, i
);
272 FcPatternAddInteger (pat
, FC_WIDTH
, FONT_WIDTH_NUMERIC (entity
));
273 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
274 val
= AREF (entity
, FONT_FAMILY_INDEX
);
276 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
277 val
= AREF (entity
, FONT_FOUNDRY_INDEX
);
279 FcPatternAddString (pat
, FC_FOUNDRY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
280 val
= AREF (entity
, FONT_SPACING_INDEX
);
282 FcPatternAddInteger (pat
, FC_SPACING
, XINT (val
));
283 val
= AREF (entity
, FONT_DPI_INDEX
);
286 double dbl
= XINT (val
);
288 FcPatternAddDouble (pat
, FC_DPI
, dbl
);
290 val
= AREF (entity
, FONT_AVGWIDTH_INDEX
);
291 if (INTEGERP (val
) && XINT (val
) == 0)
292 FcPatternAddBool (pat
, FC_SCALABLE
, FcTrue
);
293 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
294 over 10x20-ISO8859-1.pcf.gz). */
295 FcPatternAddCharSet (pat
, FC_CHARSET
, ftfont_get_fc_charset (entity
));
297 for (tail
= AREF (entity
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
299 Lisp_Object key
, val
;
301 key
= XCAR (XCAR (tail
)), val
= XCDR (XCAR (tail
));
302 if (EQ (key
, QCantialias
))
303 FcPatternAddBool (pat
, FC_ANTIALIAS
, NILP (val
) ? FcFalse
: FcTrue
);
304 else if (EQ (key
, QChinting
))
305 FcPatternAddBool (pat
, FC_HINTING
, NILP (val
) ? FcFalse
: FcTrue
);
306 else if (EQ (key
, QCautohint
))
307 FcPatternAddBool (pat
, FC_AUTOHINT
, NILP (val
) ? FcFalse
: FcTrue
);
308 else if (EQ (key
, QChintstyle
))
311 FcPatternAddInteger (pat
, FC_HINT_STYLE
, XINT (val
));
313 else if (EQ (key
, QCrgba
))
316 FcPatternAddInteger (pat
, FC_RGBA
, XINT (val
));
319 else if (EQ (key
, QCembolden
))
320 FcPatternAddBool (pat
, FC_EMBOLDEN
, NILP (val
) ? FcFalse
: FcTrue
);
324 FcPatternAddString (pat
, FC_FILE
, (FcChar8
*) SDATA (filename
));
325 FcPatternAddInteger (pat
, FC_INDEX
, XINT (index
));
329 /* Make sure that the Xrender extension is added before the Xft one.
330 Otherwise, the close-display hook set by Xft is called after the
331 one for Xrender, and the former tries to re-add the latter. This
332 results in inconsistency of internal states and leads to X
333 protocol error when one reconnects to the same X server.
336 int event_base
, error_base
;
337 XRenderQueryExtension (display
, &event_base
, &error_base
);
340 /* Substitute in values from X resources and XftDefaultSet. */
341 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
342 match
= XftFontMatch (display
, FRAME_X_SCREEN_NUMBER (f
), pat
, &result
);
343 xftfont_fix_match (pat
, match
);
345 FcPatternDestroy (pat
);
346 xftfont
= XftFontOpenPattern (display
, match
);
350 XftPatternDestroy (match
);
353 ft_face
= XftLockFace (xftfont
);
356 /* We should not destroy PAT here because it is kept in XFTFONT and
357 destroyed automatically when XFTFONT is closed. */
358 font_object
= font_make_object (VECSIZE (struct xftfont_info
), entity
, size
);
359 ASET (font_object
, FONT_TYPE_INDEX
, Qxft
);
360 len
= font_unparse_xlfd (entity
, size
, name
, 256);
362 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
363 len
= font_unparse_fcname (entity
, size
, name
, 256);
365 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
367 ASET (font_object
, FONT_FULLNAME_INDEX
,
368 AREF (font_object
, FONT_NAME_INDEX
));
369 ASET (font_object
, FONT_FILE_INDEX
, filename
);
370 ASET (font_object
, FONT_FORMAT_INDEX
,
371 ftfont_font_format (xftfont
->pattern
, filename
));
372 font
= XFONT_OBJECT (font_object
);
373 font
->pixel_size
= pixel_size
;
374 font
->driver
= &xftfont_driver
;
375 font
->encoding_charset
= font
->repertory_charset
= -1;
377 xftfont_info
= (struct xftfont_info
*) font
;
378 xftfont_info
->display
= display
;
379 xftfont_info
->screen
= FRAME_X_SCREEN_NUMBER (f
);
380 xftfont_info
->xftfont
= xftfont
;
381 font
->pixel_size
= size
;
382 font
->driver
= &xftfont_driver
;
383 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
384 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
386 spacing
= FC_PROPORTIONAL
;
387 if (! ascii_printable
[0])
390 for (i
= 0; i
< 95; i
++)
391 ascii_printable
[i
] = ' ' + i
;
394 if (spacing
!= FC_PROPORTIONAL
)
396 font
->min_width
= font
->average_width
= font
->space_width
397 = xftfont
->max_advance_width
;
398 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
402 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
403 font
->space_width
= extents
.xOff
;
404 if (font
->space_width
<= 0)
405 /* dirty workaround */
406 font
->space_width
= pixel_size
;
407 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
408 font
->average_width
= (font
->space_width
+ extents
.xOff
) / 95;
412 font
->ascent
= xftfont
->ascent
;
413 font
->descent
= xftfont
->descent
;
416 /* The above condition is a dirty workaround because
417 XftTextExtents8 behaves strangely for some fonts
418 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
419 if (font
->ascent
< extents
.y
)
420 font
->ascent
= extents
.y
;
421 if (font
->descent
< extents
.height
- extents
.y
)
422 font
->descent
= extents
.height
- extents
.y
;
424 font
->height
= font
->ascent
+ font
->descent
;
426 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) == 0)
428 int upEM
= ft_face
->units_per_EM
;
430 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
431 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
432 if (font
->underline_thickness
> 2)
433 font
->underline_position
-= font
->underline_thickness
/ 2;
437 font
->underline_position
= -1;
438 font
->underline_thickness
= 0;
441 xftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
442 xftfont_info
->otf
= NULL
;
443 #endif /* HAVE_LIBOTF */
444 xftfont_info
->ft_size
= ft_face
->size
;
446 /* Unfortunately Xft doesn't provide a way to get minimum char
447 width. So, we use space_width instead. */
448 font
->min_width
= font
->space_width
;
450 font
->baseline_offset
= 0;
451 font
->relative_compose
= 0;
452 font
->default_ascent
= 0;
453 font
->vertical_centering
= 0;
455 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
459 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
460 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
461 font
->baseline_offset
= rec
.u
.integer
;
462 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
463 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
464 font
->relative_compose
= rec
.u
.integer
;
465 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
466 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
467 font
->default_ascent
= rec
.u
.integer
;
475 xftfont_close (f
, font
)
479 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
482 if (xftfont_info
->otf
)
483 OTF_close (xftfont_info
->otf
);
486 XftUnlockFace (xftfont_info
->xftfont
);
487 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
492 xftfont_prepare_face (f
, face
)
496 struct xftface_info
*xftface_info
;
499 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
500 if (face
!= face
->ascii_face
)
502 face
->extra
= face
->ascii_face
->extra
;
507 xftface_info
= malloc (sizeof (struct xftface_info
));
510 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
511 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
512 face
->extra
= xftface_info
;
517 xftfont_done_face (f
, face
)
521 struct xftface_info
*xftface_info
;
524 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
525 if (face
!= face
->ascii_face
530 xftface_info
= (struct xftface_info
*) face
->extra
;
538 extern Lisp_Object Qja
, Qko
;
541 xftfont_has_char (font
, c
)
545 struct xftfont_info
*xftfont_info
;
546 struct charset
*cs
= NULL
;
548 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
549 && charset_jisx0208
>= 0)
550 cs
= CHARSET_FROM_ID (charset_jisx0208
);
551 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
552 && charset_ksc5601
>= 0)
553 cs
= CHARSET_FROM_ID (charset_ksc5601
);
555 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
557 if (FONT_ENTITY_P (font
))
558 return ftfont_driver
.has_char (font
, c
);
559 xftfont_info
= (struct xftfont_info
*) XFONT_OBJECT (font
);
560 return (XftCharExists (xftfont_info
->display
, xftfont_info
->xftfont
,
561 (FcChar32
) c
) == FcTrue
);
565 xftfont_encode_char (font
, c
)
569 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
570 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
573 return (code
? code
: FONT_INVALID_CODE
);
577 xftfont_text_extents (font
, code
, nglyphs
, metrics
)
581 struct font_metrics
*metrics
;
583 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
587 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
592 metrics
->lbearing
= - extents
.x
;
593 metrics
->rbearing
= - extents
.x
+ extents
.width
;
594 metrics
->width
= extents
.xOff
;
595 metrics
->ascent
= extents
.y
;
596 metrics
->descent
= extents
.height
- extents
.y
;
602 xftfont_get_xft_draw (f
)
605 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
610 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
613 FRAME_X_COLORMAP (f
));
617 font_put_frame_data (f
, &xftfont_driver
, xft_draw
);
623 xftfont_draw (s
, from
, to
, x
, y
, with_background
)
624 struct glyph_string
*s
;
625 int from
, to
, x
, y
, with_background
;
628 struct face
*face
= s
->face
;
629 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
630 struct xftface_info
*xftface_info
= NULL
;
631 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
637 if (s
->font
== face
->font
)
638 xftface_info
= (struct xftface_info
*) face
->extra
;
639 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
640 &fg
, with_background
? &bg
: NULL
);
642 if (s
->num_clips
> 0)
643 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
645 XftDrawSetClip (xft_draw
, NULL
);
648 XftDrawRect (xft_draw
, &bg
,
649 x
, y
- face
->font
->ascent
, s
->width
, face
->font
->height
);
650 code
= alloca (sizeof (FT_UInt
) * len
);
651 for (i
= 0; i
< len
; i
++)
652 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
653 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
656 for (i
= 0; i
< len
; i
++)
657 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
658 x
+ i
, y
, code
+ i
, 1);
660 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
668 xftfont_end_for_frame (f
)
673 /* Don't do anything if display is dead */
674 if (FRAME_X_DISPLAY (f
) == NULL
) return 0;
676 xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
681 XftDrawDestroy (xft_draw
);
683 font_put_frame_data (f
, &xftfont_driver
, NULL
);
691 DEFSYM (Qxft
, "xft");
692 DEFSYM (QChinting
, ":hinting");
693 DEFSYM (QCautohint
, ":autohint");
694 DEFSYM (QChintstyle
, ":hintstyle");
695 DEFSYM (QCrgba
, ":rgba");
696 DEFSYM (QCembolden
, ":embolden");
698 xftfont_driver
= ftfont_driver
;
699 xftfont_driver
.type
= Qxft
;
700 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
701 xftfont_driver
.list
= xftfont_list
;
702 xftfont_driver
.match
= xftfont_match
;
703 xftfont_driver
.open
= xftfont_open
;
704 xftfont_driver
.close
= xftfont_close
;
705 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
706 xftfont_driver
.done_face
= xftfont_done_face
;
707 xftfont_driver
.has_char
= xftfont_has_char
;
708 xftfont_driver
.encode_char
= xftfont_encode_char
;
709 xftfont_driver
.text_extents
= xftfont_text_extents
;
710 xftfont_driver
.draw
= xftfont_draw
;
711 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
713 register_font_driver (&xftfont_driver
, NULL
);
716 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
717 (do not change this comment) */