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_open (f
, entity
, pixel_size
)
194 Display
*display
= FRAME_X_DISPLAY (f
);
195 Lisp_Object val
, filename
, index
, tail
, font_object
;
196 FcPattern
*pat
= NULL
, *match
;
197 struct xftfont_info
*xftfont_info
= NULL
;
200 XftFont
*xftfont
= NULL
;
207 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
211 filename
= XCAR (val
);
213 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
216 pat
= FcPatternCreate ();
217 FcPatternAddInteger (pat
, FC_WEIGHT
, FONT_WEIGHT_NUMERIC (entity
));
218 i
= FONT_SLANT_NUMERIC (entity
) - 100;
220 FcPatternAddInteger (pat
, FC_SLANT
, i
);
221 FcPatternAddInteger (pat
, FC_WIDTH
, FONT_WIDTH_NUMERIC (entity
));
222 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
223 val
= AREF (entity
, FONT_FAMILY_INDEX
);
225 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
226 val
= AREF (entity
, FONT_FOUNDRY_INDEX
);
228 FcPatternAddString (pat
, FC_FOUNDRY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
229 val
= AREF (entity
, FONT_SPACING_INDEX
);
231 FcPatternAddInteger (pat
, FC_SPACING
, XINT (val
));
232 val
= AREF (entity
, FONT_DPI_INDEX
);
235 double dbl
= XINT (val
);
237 FcPatternAddDouble (pat
, FC_DPI
, dbl
);
239 val
= AREF (entity
, FONT_AVGWIDTH_INDEX
);
240 if (INTEGERP (val
) && XINT (val
) == 0)
241 FcPatternAddBool (pat
, FC_SCALABLE
, FcTrue
);
242 /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
243 over 10x20-ISO8859-1.pcf.gz). */
244 FcPatternAddCharSet (pat
, FC_CHARSET
, ftfont_get_fc_charset (entity
));
246 for (tail
= AREF (entity
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
248 Lisp_Object key
, val
;
250 key
= XCAR (XCAR (tail
)), val
= XCDR (XCAR (tail
));
251 if (EQ (key
, QCantialias
))
252 FcPatternAddBool (pat
, FC_ANTIALIAS
, NILP (val
) ? FcFalse
: FcTrue
);
253 else if (EQ (key
, QChinting
))
254 FcPatternAddBool (pat
, FC_HINTING
, NILP (val
) ? FcFalse
: FcTrue
);
255 else if (EQ (key
, QCautohint
))
256 FcPatternAddBool (pat
, FC_AUTOHINT
, NILP (val
) ? FcFalse
: FcTrue
);
257 else if (EQ (key
, QChintstyle
))
260 FcPatternAddInteger (pat
, FC_HINT_STYLE
, XINT (val
));
262 else if (EQ (key
, QCrgba
))
265 FcPatternAddInteger (pat
, FC_RGBA
, XINT (val
));
268 else if (EQ (key
, QCembolden
))
269 FcPatternAddBool (pat
, FC_EMBOLDEN
, NILP (val
) ? FcFalse
: FcTrue
);
273 FcPatternAddString (pat
, FC_FILE
, (FcChar8
*) SDATA (filename
));
274 FcPatternAddInteger (pat
, FC_INDEX
, XINT (index
));
278 /* Make sure that the Xrender extension is added before the Xft one.
279 Otherwise, the close-display hook set by Xft is called after the
280 one for Xrender, and the former tries to re-add the latter. This
281 results in inconsistency of internal states and leads to X
282 protocol error when one reconnects to the same X server.
285 int event_base
, error_base
;
286 XRenderQueryExtension (display
, &event_base
, &error_base
);
288 match
= XftFontMatch (display
, FRAME_X_SCREEN_NUMBER (f
), pat
, &result
);
289 FcPatternDestroy (pat
);
290 xftfont
= XftFontOpenPattern (display
, match
);
294 XftPatternDestroy (match
);
297 ft_face
= XftLockFace (xftfont
);
300 /* We should not destroy PAT here because it is kept in XFTFONT and
301 destroyed automatically when XFTFONT is closed. */
302 font_object
= font_make_object (VECSIZE (struct xftfont_info
), entity
, size
);
303 ASET (font_object
, FONT_TYPE_INDEX
, Qxft
);
304 len
= font_unparse_xlfd (entity
, size
, name
, 256);
306 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
307 len
= font_unparse_fcname (entity
, size
, name
, 256);
309 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
311 ASET (font_object
, FONT_FULLNAME_INDEX
,
312 AREF (font_object
, FONT_NAME_INDEX
));
313 ASET (font_object
, FONT_FILE_INDEX
, filename
);
314 ASET (font_object
, FONT_FORMAT_INDEX
,
315 ftfont_font_format (xftfont
->pattern
, filename
));
316 font
= XFONT_OBJECT (font_object
);
317 font
->pixel_size
= pixel_size
;
318 font
->driver
= &xftfont_driver
;
319 font
->encoding_charset
= font
->repertory_charset
= -1;
321 xftfont_info
= (struct xftfont_info
*) font
;
322 xftfont_info
->display
= display
;
323 xftfont_info
->screen
= FRAME_X_SCREEN_NUMBER (f
);
324 xftfont_info
->xftfont
= xftfont
;
325 font
->pixel_size
= size
;
326 font
->driver
= &xftfont_driver
;
327 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
328 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
330 spacing
= FC_PROPORTIONAL
;
331 if (! ascii_printable
[0])
334 for (i
= 0; i
< 95; i
++)
335 ascii_printable
[i
] = ' ' + i
;
338 if (spacing
!= FC_PROPORTIONAL
)
340 font
->min_width
= font
->average_width
= font
->space_width
341 = xftfont
->max_advance_width
;
342 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
346 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
347 font
->space_width
= extents
.xOff
;
348 if (font
->space_width
<= 0)
349 /* dirty workaround */
350 font
->space_width
= pixel_size
;
351 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
352 font
->average_width
= (font
->space_width
+ extents
.xOff
) / 95;
356 font
->ascent
= xftfont
->ascent
;
357 font
->descent
= xftfont
->descent
;
360 /* The above condition is a dirty workaround because
361 XftTextExtents8 behaves strangely for some fonts
362 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
363 if (font
->ascent
< extents
.y
)
364 font
->ascent
= extents
.y
;
365 if (font
->descent
< extents
.height
- extents
.y
)
366 font
->descent
= extents
.height
- extents
.y
;
368 font
->height
= font
->ascent
+ font
->descent
;
370 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) == 0)
372 int upEM
= ft_face
->units_per_EM
;
374 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
375 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
376 if (font
->underline_thickness
> 2)
377 font
->underline_position
-= font
->underline_thickness
/ 2;
381 font
->underline_position
= -1;
382 font
->underline_thickness
= 0;
385 xftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
386 xftfont_info
->otf
= NULL
;
387 #endif /* HAVE_LIBOTF */
388 xftfont_info
->ft_size
= ft_face
->size
;
390 /* Unfortunately Xft doesn't provide a way to get minimum char
391 width. So, we use space_width instead. */
392 font
->min_width
= font
->space_width
;
394 font
->baseline_offset
= 0;
395 font
->relative_compose
= 0;
396 font
->default_ascent
= 0;
397 font
->vertical_centering
= 0;
399 if (! (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
))
403 if (FT_Get_BDF_Property (ft_face
, "_MULE_BASELINE_OFFSET", &rec
) == 0
404 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
405 font
->baseline_offset
= rec
.u
.integer
;
406 if (FT_Get_BDF_Property (ft_face
, "_MULE_RELATIVE_COMPOSE", &rec
) == 0
407 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
408 font
->relative_compose
= rec
.u
.integer
;
409 if (FT_Get_BDF_Property (ft_face
, "_MULE_DEFAULT_ASCENT", &rec
) == 0
410 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
411 font
->default_ascent
= rec
.u
.integer
;
419 xftfont_close (f
, font
)
423 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
426 if (xftfont_info
->otf
)
427 OTF_close (xftfont_info
->otf
);
430 XftUnlockFace (xftfont_info
->xftfont
);
431 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
436 xftfont_prepare_face (f
, face
)
440 struct xftface_info
*xftface_info
;
443 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
444 if (face
!= face
->ascii_face
)
446 face
->extra
= face
->ascii_face
->extra
;
451 xftface_info
= malloc (sizeof (struct xftface_info
));
454 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
455 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
456 face
->extra
= xftface_info
;
461 xftfont_done_face (f
, face
)
465 struct xftface_info
*xftface_info
;
468 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
469 if (face
!= face
->ascii_face
474 xftface_info
= (struct xftface_info
*) face
->extra
;
482 extern Lisp_Object Qja
, Qko
;
485 xftfont_has_char (font
, c
)
489 struct xftfont_info
*xftfont_info
;
490 struct charset
*cs
= NULL
;
492 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
493 && charset_jisx0208
>= 0)
494 cs
= CHARSET_FROM_ID (charset_jisx0208
);
495 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
496 && charset_ksc5601
>= 0)
497 cs
= CHARSET_FROM_ID (charset_ksc5601
);
499 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
501 if (FONT_ENTITY_P (font
))
502 return ftfont_driver
.has_char (font
, c
);
503 xftfont_info
= (struct xftfont_info
*) XFONT_OBJECT (font
);
504 return (XftCharExists (xftfont_info
->display
, xftfont_info
->xftfont
,
505 (FcChar32
) c
) == FcTrue
);
509 xftfont_encode_char (font
, c
)
513 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
514 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
517 return (code
? code
: FONT_INVALID_CODE
);
521 xftfont_text_extents (font
, code
, nglyphs
, metrics
)
525 struct font_metrics
*metrics
;
527 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
531 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
536 metrics
->lbearing
= - extents
.x
;
537 metrics
->rbearing
= - extents
.x
+ extents
.width
;
538 metrics
->width
= extents
.xOff
;
539 metrics
->ascent
= extents
.y
;
540 metrics
->descent
= extents
.height
- extents
.y
;
546 xftfont_get_xft_draw (f
)
549 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
554 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
557 FRAME_X_COLORMAP (f
));
561 font_put_frame_data (f
, &xftfont_driver
, xft_draw
);
567 xftfont_draw (s
, from
, to
, x
, y
, with_background
)
568 struct glyph_string
*s
;
569 int from
, to
, x
, y
, with_background
;
572 struct face
*face
= s
->face
;
573 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font
;
574 struct xftface_info
*xftface_info
= NULL
;
575 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
581 if (s
->font
== face
->font
)
582 xftface_info
= (struct xftface_info
*) face
->extra
;
583 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
584 &fg
, with_background
? &bg
: NULL
);
586 if (s
->num_clips
> 0)
587 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
589 XftDrawSetClip (xft_draw
, NULL
);
592 XftDrawRect (xft_draw
, &bg
,
593 x
, y
- face
->font
->ascent
, s
->width
, face
->font
->height
);
594 code
= alloca (sizeof (FT_UInt
) * len
);
595 for (i
= 0; i
< len
; i
++)
596 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
597 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
600 for (i
= 0; i
< len
; i
++)
601 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
602 x
+ i
, y
, code
+ i
, 1);
604 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
612 xftfont_end_for_frame (f
)
615 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
620 XftDrawDestroy (xft_draw
);
622 font_put_frame_data (f
, &xftfont_driver
, NULL
);
630 DEFSYM (Qxft
, "xft");
631 DEFSYM (QChinting
, ":hinting");
632 DEFSYM (QCautohint
, ":autohint");
633 DEFSYM (QChintstyle
, ":hintstyle");
634 DEFSYM (QCrgba
, ":rgba");
635 DEFSYM (QCembolden
, ":embolden");
637 xftfont_driver
= ftfont_driver
;
638 xftfont_driver
.type
= Qxft
;
639 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
640 xftfont_driver
.list
= xftfont_list
;
641 xftfont_driver
.match
= xftfont_match
;
642 xftfont_driver
.open
= xftfont_open
;
643 xftfont_driver
.close
= xftfont_close
;
644 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
645 xftfont_driver
.done_face
= xftfont_done_face
;
646 xftfont_driver
.has_char
= xftfont_has_char
;
647 xftfont_driver
.encode_char
= xftfont_encode_char
;
648 xftfont_driver
.text_extents
= xftfont_text_extents
;
649 xftfont_driver
.draw
= xftfont_draw
;
650 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
652 register_font_driver (&xftfont_driver
, NULL
);
655 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
656 (do not change this comment) */