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
);
218 /* Older fontconfig versions don't have FC_LCD_FILTER. */
219 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_LCD_FILTER
, 0, &i
))
221 FcPatternDel (match
, FC_LCD_FILTER
);
222 FcPatternAddInteger (match
, FC_LCD_FILTER
, i
);
225 if (FcResultMatch
== FcPatternGetInteger (pat
, FC_RGBA
, 0, &i
))
227 FcPatternDel (match
, FC_RGBA
);
228 FcPatternAddInteger (match
, FC_RGBA
, i
);
230 if (FcResultMatch
== FcPatternGetDouble (pat
, FC_DPI
, 0, &dpi
))
232 FcPatternDel (match
, FC_DPI
);
233 FcPatternAddDouble (match
, FC_DPI
, dpi
);
238 xftfont_open (f
, entity
, pixel_size
)
244 Display
*display
= FRAME_X_DISPLAY (f
);
245 Lisp_Object val
, filename
, index
, tail
, font_object
;
246 FcPattern
*pat
= NULL
, *match
;
247 struct xftfont_info
*xftfont_info
= NULL
;
250 XftFont
*xftfont
= NULL
;
257 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
261 filename
= XCAR (val
);
263 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
266 pat
= FcPatternCreate ();
267 FcPatternAddInteger (pat
, FC_WEIGHT
, FONT_WEIGHT_NUMERIC (entity
));
268 i
= FONT_SLANT_NUMERIC (entity
) - 100;
270 FcPatternAddInteger (pat
, FC_SLANT
, i
);
271 FcPatternAddInteger (pat
, FC_WIDTH
, FONT_WIDTH_NUMERIC (entity
));
272 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
273 val
= AREF (entity
, FONT_FAMILY_INDEX
);
275 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
276 val
= AREF (entity
, FONT_FOUNDRY_INDEX
);
278 FcPatternAddString (pat
, FC_FOUNDRY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
279 val
= AREF (entity
, FONT_SPACING_INDEX
);
281 FcPatternAddInteger (pat
, FC_SPACING
, XINT (val
));
282 val
= AREF (entity
, FONT_DPI_INDEX
);
285 double dbl
= XINT (val
);
287 FcPatternAddDouble (pat
, FC_DPI
, dbl
);
289 val
= AREF (entity
, FONT_AVGWIDTH_INDEX
);
290 if (INTEGERP (val
) && XINT (val
) == 0)
291 FcPatternAddBool (pat
, FC_SCALABLE
, FcTrue
);
292 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
293 over 10x20-ISO8859-1.pcf.gz). */
294 FcPatternAddCharSet (pat
, FC_CHARSET
, ftfont_get_fc_charset (entity
));
296 for (tail
= AREF (entity
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
298 Lisp_Object key
, val
;
300 key
= XCAR (XCAR (tail
)), val
= XCDR (XCAR (tail
));
301 if (EQ (key
, QCantialias
))
302 FcPatternAddBool (pat
, FC_ANTIALIAS
, NILP (val
) ? FcFalse
: FcTrue
);
303 else if (EQ (key
, QChinting
))
304 FcPatternAddBool (pat
, FC_HINTING
, NILP (val
) ? FcFalse
: FcTrue
);
305 else if (EQ (key
, QCautohint
))
306 FcPatternAddBool (pat
, FC_AUTOHINT
, NILP (val
) ? FcFalse
: FcTrue
);
307 else if (EQ (key
, QChintstyle
))
310 FcPatternAddInteger (pat
, FC_HINT_STYLE
, XINT (val
));
312 else if (EQ (key
, QCrgba
))
315 FcPatternAddInteger (pat
, FC_RGBA
, XINT (val
));
318 else if (EQ (key
, QCembolden
))
319 FcPatternAddBool (pat
, FC_EMBOLDEN
, NILP (val
) ? FcFalse
: FcTrue
);
323 FcPatternAddString (pat
, FC_FILE
, (FcChar8
*) SDATA (filename
));
324 FcPatternAddInteger (pat
, FC_INDEX
, XINT (index
));
328 /* Make sure that the Xrender extension is added before the Xft one.
329 Otherwise, the close-display hook set by Xft is called after the
330 one for Xrender, and the former tries to re-add the latter. This
331 results in inconsistency of internal states and leads to X
332 protocol error when one reconnects to the same X server.
335 int event_base
, error_base
;
336 XRenderQueryExtension (display
, &event_base
, &error_base
);
339 /* Substitute in values from X resources and XftDefaultSet. */
340 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
341 match
= XftFontMatch (display
, FRAME_X_SCREEN_NUMBER (f
), pat
, &result
);
342 xftfont_fix_match (pat
, match
);
344 FcPatternDestroy (pat
);
345 xftfont
= XftFontOpenPattern (display
, match
);
349 XftPatternDestroy (match
);
352 ft_face
= XftLockFace (xftfont
);
355 /* We should not destroy PAT here because it is kept in XFTFONT and
356 destroyed automatically when XFTFONT is closed. */
357 font_object
= font_make_object (VECSIZE (struct xftfont_info
), entity
, size
);
358 ASET (font_object
, FONT_TYPE_INDEX
, Qxft
);
359 len
= font_unparse_xlfd (entity
, size
, name
, 256);
361 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
362 len
= font_unparse_fcname (entity
, size
, name
, 256);
364 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
366 ASET (font_object
, FONT_FULLNAME_INDEX
,
367 AREF (font_object
, FONT_NAME_INDEX
));
368 ASET (font_object
, FONT_FILE_INDEX
, filename
);
369 ASET (font_object
, FONT_FORMAT_INDEX
,
370 ftfont_font_format (xftfont
->pattern
, filename
));
371 font
= XFONT_OBJECT (font_object
);
372 font
->pixel_size
= pixel_size
;
373 font
->driver
= &xftfont_driver
;
374 font
->encoding_charset
= font
->repertory_charset
= -1;
376 xftfont_info
= (struct xftfont_info
*) font
;
377 xftfont_info
->display
= display
;
378 xftfont_info
->screen
= FRAME_X_SCREEN_NUMBER (f
);
379 xftfont_info
->xftfont
= xftfont
;
380 font
->pixel_size
= size
;
381 font
->driver
= &xftfont_driver
;
382 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
383 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
385 spacing
= FC_PROPORTIONAL
;
386 if (! ascii_printable
[0])
389 for (i
= 0; i
< 95; i
++)
390 ascii_printable
[i
] = ' ' + i
;
393 if (spacing
!= FC_PROPORTIONAL
)
395 font
->min_width
= font
->average_width
= font
->space_width
396 = xftfont
->max_advance_width
;
397 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
401 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
402 font
->space_width
= extents
.xOff
;
403 if (font
->space_width
<= 0)
404 /* dirty workaround */
405 font
->space_width
= pixel_size
;
406 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
407 font
->average_width
= (font
->space_width
+ extents
.xOff
) / 95;
411 font
->ascent
= xftfont
->ascent
;
412 font
->descent
= xftfont
->descent
;
415 /* The above condition is a dirty workaround because
416 XftTextExtents8 behaves strangely for some fonts
417 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
418 if (font
->ascent
< extents
.y
)
419 font
->ascent
= extents
.y
;
420 if (font
->descent
< extents
.height
- extents
.y
)
421 font
->descent
= extents
.height
- extents
.y
;
423 font
->height
= font
->ascent
+ font
->descent
;
425 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) == 0)
427 int upEM
= ft_face
->units_per_EM
;
429 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
430 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
431 if (font
->underline_thickness
> 2)
432 font
->underline_position
-= font
->underline_thickness
/ 2;
436 font
->underline_position
= -1;
437 font
->underline_thickness
= 0;
440 xftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
441 xftfont_info
->otf
= NULL
;
442 #endif /* HAVE_LIBOTF */
443 xftfont_info
->ft_size
= ft_face
->size
;
445 /* Unfortunately Xft doesn't provide a way to get minimum char
446 width. So, we use space_width instead. */
447 font
->min_width
= font
->space_width
;
449 font
->baseline_offset
= 0;
450 font
->relative_compose
= 0;
451 font
->default_ascent
= 0;
452 font
->vertical_centering
= 0;
454 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
458 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
459 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
460 font
->baseline_offset
= rec
.u
.integer
;
461 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
462 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
463 font
->relative_compose
= rec
.u
.integer
;
464 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
465 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
466 font
->default_ascent
= rec
.u
.integer
;
474 xftfont_close (f
, font
)
478 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
481 if (xftfont_info
->otf
)
482 OTF_close (xftfont_info
->otf
);
485 XftUnlockFace (xftfont_info
->xftfont
);
486 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
491 xftfont_prepare_face (f
, face
)
495 struct xftface_info
*xftface_info
;
498 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
499 if (face
!= face
->ascii_face
)
501 face
->extra
= face
->ascii_face
->extra
;
506 xftface_info
= malloc (sizeof (struct xftface_info
));
509 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
510 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
511 face
->extra
= xftface_info
;
516 xftfont_done_face (f
, face
)
520 struct xftface_info
*xftface_info
;
523 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
524 if (face
!= face
->ascii_face
529 xftface_info
= (struct xftface_info
*) face
->extra
;
537 extern Lisp_Object Qja
, Qko
;
540 xftfont_has_char (font
, c
)
544 struct xftfont_info
*xftfont_info
;
545 struct charset
*cs
= NULL
;
547 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
548 && charset_jisx0208
>= 0)
549 cs
= CHARSET_FROM_ID (charset_jisx0208
);
550 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
551 && charset_ksc5601
>= 0)
552 cs
= CHARSET_FROM_ID (charset_ksc5601
);
554 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
556 if (FONT_ENTITY_P (font
))
557 return ftfont_driver
.has_char (font
, c
);
558 xftfont_info
= (struct xftfont_info
*) XFONT_OBJECT (font
);
559 return (XftCharExists (xftfont_info
->display
, xftfont_info
->xftfont
,
560 (FcChar32
) c
) == FcTrue
);
564 xftfont_encode_char (font
, c
)
568 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
569 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
572 return (code
? code
: FONT_INVALID_CODE
);
576 xftfont_text_extents (font
, code
, nglyphs
, metrics
)
580 struct font_metrics
*metrics
;
582 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
586 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
591 metrics
->lbearing
= - extents
.x
;
592 metrics
->rbearing
= - extents
.x
+ extents
.width
;
593 metrics
->width
= extents
.xOff
;
594 metrics
->ascent
= extents
.y
;
595 metrics
->descent
= extents
.height
- extents
.y
;
601 xftfont_get_xft_draw (f
)
604 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
609 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
612 FRAME_X_COLORMAP (f
));
616 font_put_frame_data (f
, &xftfont_driver
, xft_draw
);
622 xftfont_draw (s
, from
, to
, x
, y
, with_background
)
623 struct glyph_string
*s
;
624 int from
, to
, x
, y
, with_background
;
627 struct face
*face
= s
->face
;
628 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
629 struct xftface_info
*xftface_info
= NULL
;
630 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
636 if (s
->font
== face
->font
)
637 xftface_info
= (struct xftface_info
*) face
->extra
;
638 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
639 &fg
, with_background
? &bg
: NULL
);
641 if (s
->num_clips
> 0)
642 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
644 XftDrawSetClip (xft_draw
, NULL
);
647 XftDrawRect (xft_draw
, &bg
,
648 x
, y
- face
->font
->ascent
, s
->width
, face
->font
->height
);
649 code
= alloca (sizeof (FT_UInt
) * len
);
650 for (i
= 0; i
< len
; i
++)
651 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
652 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
655 for (i
= 0; i
< len
; i
++)
656 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
657 x
+ i
, y
, code
+ i
, 1);
659 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
667 xftfont_end_for_frame (f
)
670 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
675 XftDrawDestroy (xft_draw
);
677 font_put_frame_data (f
, &xftfont_driver
, NULL
);
685 DEFSYM (Qxft
, "xft");
686 DEFSYM (QChinting
, ":hinting");
687 DEFSYM (QCautohint
, ":autohint");
688 DEFSYM (QChintstyle
, ":hintstyle");
689 DEFSYM (QCrgba
, ":rgba");
690 DEFSYM (QCembolden
, ":embolden");
692 xftfont_driver
= ftfont_driver
;
693 xftfont_driver
.type
= Qxft
;
694 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
695 xftfont_driver
.list
= xftfont_list
;
696 xftfont_driver
.match
= xftfont_match
;
697 xftfont_driver
.open
= xftfont_open
;
698 xftfont_driver
.close
= xftfont_close
;
699 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
700 xftfont_driver
.done_face
= xftfont_done_face
;
701 xftfont_driver
.has_char
= xftfont_has_char
;
702 xftfont_driver
.encode_char
= xftfont_encode_char
;
703 xftfont_driver
.text_extents
= xftfont_text_extents
;
704 xftfont_driver
.draw
= xftfont_draw
;
705 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
707 register_font_driver (&xftfont_driver
, NULL
);
710 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
711 (do not change this comment) */