1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006 Free Software Foundation, Inc.
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 2, or (at your option)
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; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA. */
27 #include <X11/Xft/Xft.h>
30 #include "dispextern.h"
33 #include "blockinput.h"
34 #include "character.h"
39 /* Xft font driver. */
41 static Lisp_Object Qxft
;
43 /* The actual structure for Xft font that can be casted to struct
55 /* Structure pointed by (struct face *)->extra */
63 static void xftfont_get_colors
P_ ((FRAME_PTR
, struct face
*, GC gc
,
64 struct xftface_info
*,
65 XftColor
*fg
, XftColor
*bg
));
66 static Font xftfont_default_fid
P_ ((FRAME_PTR
));
69 /* Setup colors pointed by FG and BG for GC. If XFTFACE_INFO is not
70 NULL, reuse the colors in it if possible. BG may be NULL. */
72 xftfont_get_colors (f
, face
, gc
, xftface_info
, fg
, bg
)
76 struct xftface_info
*xftface_info
;
79 if (xftface_info
&& face
->gc
== gc
)
81 *fg
= xftface_info
->xft_fg
;
83 *bg
= xftface_info
->xft_bg
;
88 int fg_done
= 0, bg_done
= 0;
91 XGetGCValues (FRAME_X_DISPLAY (f
), gc
,
92 GCForeground
| GCBackground
, &xgcv
);
95 if (xgcv
.foreground
== face
->foreground
)
96 *fg
= xftface_info
->xft_fg
, fg_done
= 1;
97 else if (xgcv
.foreground
== face
->background
)
98 *fg
= xftface_info
->xft_bg
, fg_done
= 1;
101 else if (xgcv
.background
== face
->background
)
102 *bg
= xftface_info
->xft_bg
, bg_done
= 1;
103 else if (xgcv
.background
== face
->foreground
)
104 *bg
= xftface_info
->xft_fg
, bg_done
= 1;
107 if (fg_done
+ bg_done
< 2)
111 colors
[0].pixel
= fg
->pixel
= xgcv
.foreground
;
113 colors
[1].pixel
= bg
->pixel
= xgcv
.background
;
114 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
,
116 fg
->color
.alpha
= 0xFFFF;
117 fg
->color
.red
= colors
[0].red
;
118 fg
->color
.green
= colors
[0].green
;
119 fg
->color
.blue
= colors
[0].blue
;
122 bg
->color
.alpha
= 0xFFFF;
123 bg
->color
.red
= colors
[1].red
;
124 bg
->color
.green
= colors
[1].green
;
125 bg
->color
.blue
= colors
[1].blue
;
132 /* Return the default Font ID on frame F. */
135 xftfont_default_fid (f
)
138 static int fid_known
;
143 fid
= XLoadFont (FRAME_X_DISPLAY (f
), "fixed");
146 fid
= XLoadFont (FRAME_X_DISPLAY (f
), "*");
156 static Lisp_Object xftfont_list
P_ ((Lisp_Object
, Lisp_Object
));
157 static struct font
*xftfont_open
P_ ((FRAME_PTR
, Lisp_Object
, int));
158 static void xftfont_close
P_ ((FRAME_PTR
, struct font
*));
159 static int xftfont_prepare_face
P_ ((FRAME_PTR
, struct face
*));
160 static void xftfont_done_face
P_ ((FRAME_PTR
, struct face
*));
161 static unsigned xftfont_encode_char
P_ ((struct font
*, int));
162 static int xftfont_text_extents
P_ ((struct font
*, unsigned *, int,
163 struct font_metrics
*));
164 static int xftfont_draw
P_ ((struct glyph_string
*, int, int, int, int, int));
166 static int xftfont_anchor_point
P_ ((struct font
*, unsigned, int,
169 struct font_driver xftfont_driver
;
172 xftfont_list (frame
, spec
)
176 Lisp_Object val
= ftfont_driver
.list (frame
, spec
);
182 for (i
= 0; i
< ASIZE (val
); i
++)
183 ASET (AREF (val
, i
), FONT_TYPE_INDEX
, Qxft
);
188 static FcChar8 ascii_printable
[95];
191 xftfont_open (f
, entity
, pixel_size
)
196 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
197 Display
*display
= FRAME_X_DISPLAY (f
);
199 FcPattern
*pattern
, *pat
;
202 struct xftfont_info
*xftfont_info
;
208 val
= AREF (entity
, FONT_EXTRA_INDEX
);
209 if (XTYPE (val
) != Lisp_Misc
210 || XMISCTYPE (val
) != Lisp_Misc_Save_Value
)
212 pattern
= XSAVE_VALUE (val
)->pointer
;
213 if (FcPatternGetString (pattern
, FC_FILE
, 0, &file
) != FcResultMatch
)
216 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
219 pat
= FcPatternCreate ();
220 FcPatternAddString (pat
, FC_FILE
, file
);
221 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
222 FcPatternAddBool (pat
, FC_ANTIALIAS
, FcTrue
);
223 xftfont
= XftFontOpenPattern (display
, pat
);
224 /* We should not destroy PAT here because it is kept in XFTFONT and
225 destroyed automatically when XFTFONT is closed. */
229 xftfont_info
= malloc (sizeof (struct xftfont_info
));
232 XftFontClose (display
, xftfont
);
235 xfont
= malloc (sizeof (XFontStruct
));
238 XftFontClose (display
, xftfont
);
242 xftfont_info
->display
= display
;
243 xftfont_info
->screen
= FRAME_X_SCREEN_NUMBER (f
);
244 xftfont_info
->xftfont
= xftfont
;
245 xftfont_info
->ft_face
= XftLockFace (xftfont
);
247 font
= (struct font
*) xftfont_info
;
248 font
->entity
= entity
;
249 font
->pixel_size
= size
;
250 font
->driver
= &xftfont_driver
;
251 font
->font
.name
= font
->font
.full_name
= NULL
;
252 font
->file_name
= (char *) file
;
253 font
->font
.size
= xftfont
->max_advance_width
;
254 font
->ascent
= xftfont
->ascent
;
255 font
->descent
= xftfont
->descent
;
256 font
->font
.height
= xftfont
->ascent
+ xftfont
->descent
;
258 if (FcPatternGetInteger (xftfont
->pattern
, FC_SPACING
, 0, &spacing
)
260 spacing
= FC_PROPORTIONAL
;
261 if (spacing
!= FC_PROPORTIONAL
)
262 font
->font
.average_width
= font
->font
.space_width
263 = xftfont
->max_advance_width
;
268 if (! ascii_printable
[0])
271 for (i
= 0; i
< 95; i
++)
272 ascii_printable
[i
] = ' ' + i
;
274 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
275 font
->font
.space_width
= extents
.xOff
;
276 if (font
->font
.space_width
<= 0)
277 /* dirty workaround */
278 font
->font
.space_width
= pixel_size
;
279 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
280 font
->font
.average_width
= (font
->font
.space_width
+ extents
.xOff
) / 95;
283 /* Unfortunately Xft doesn't provide a way to get minimum char
284 width. So, we use space_width instead. */
285 font
->min_width
= font
->font
.space_width
;
287 font
->font
.baseline_offset
= 0;
288 font
->font
.relative_compose
= 0;
289 font
->font
.default_ascent
= 0;
290 font
->font
.vertical_centering
= 0;
292 /* Setup pseudo XFontStruct */
293 xfont
->fid
= xftfont_default_fid (f
);
294 xfont
->ascent
= xftfont
->ascent
;
295 xfont
->descent
= xftfont
->descent
;
296 xfont
->max_bounds
.descent
= xftfont
->descent
;
297 xfont
->max_bounds
.width
= xftfont
->max_advance_width
;
298 xfont
->min_bounds
.width
= font
->font
.space_width
;
299 font
->font
.font
= xfont
;
303 /* Set global flag fonts_changed_p to non-zero if the font loaded
304 has a character with a smaller width than any other character
305 before, or if the font loaded has a smaller height than any other
306 font loaded before. If this happens, it will make a glyph matrix
307 reallocation necessary. */
308 if (dpyinfo
->n_fonts
== 1)
310 dpyinfo
->smallest_font_height
= font
->font
.height
;
311 dpyinfo
->smallest_char_width
= font
->min_width
;
316 if (dpyinfo
->smallest_font_height
> font
->font
.height
)
317 dpyinfo
->smallest_font_height
= font
->font
.height
,
318 fonts_changed_p
|= 1;
319 if (dpyinfo
->smallest_char_width
> font
->min_width
)
320 dpyinfo
->smallest_char_width
= font
->min_width
,
321 fonts_changed_p
|= 1;
328 xftfont_close (f
, font
)
332 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
334 XftUnlockFace (xftfont_info
->xftfont
);
335 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
337 FRAME_X_DISPLAY_INFO (f
)->n_fonts
--;
341 xftfont_prepare_face (f
, face
)
345 struct xftface_info
*xftface_info
= malloc (sizeof (struct xftface_info
));
351 xftface_info
->xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
354 FRAME_X_COLORMAP (f
));
355 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
356 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
359 face
->extra
= xftface_info
;
364 xftfont_done_face (f
, face
)
368 struct xftface_info
*xftface_info
= (struct xftface_info
*) face
->extra
;
373 XftDrawDestroy (xftface_info
->xft_draw
);
381 xftfont_encode_char (font
, c
)
385 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
386 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
389 return (code
? code
: 0xFFFFFFFF);
393 xftfont_text_extents (font
, code
, nglyphs
, metrics
)
397 struct font_metrics
*metrics
;
399 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
403 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
408 metrics
->lbearing
= - extents
.x
;
409 metrics
->rbearing
= - extents
.x
+ extents
.width
;
410 metrics
->width
= extents
.xOff
;
411 metrics
->ascent
= extents
.y
;
412 metrics
->descent
= extents
.y
- extents
.height
;
418 xftfont_draw (s
, from
, to
, x
, y
, with_background
)
419 struct glyph_string
*s
;
420 int from
, to
, x
, y
, with_background
;
423 struct face
*face
= s
->face
;
424 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) face
->font_info
;
425 struct xftface_info
*xftface_info
= (struct xftface_info
*) face
->extra
;
432 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
433 &fg
, with_background
? &bg
: NULL
);
437 r
.x
= s
->clip_x
, r
.width
= s
->clip_width
;
438 r
.y
= s
->clip_y
, r
.height
= s
->clip_height
;
439 XftDrawSetClipRectangles (xftface_info
->xft_draw
, 0, 0, &r
, 1);
443 struct font
*font
= (struct font
*) face
->font_info
;
445 XftDrawRect (xftface_info
->xft_draw
, &bg
,
446 x
, y
- face
->font
->ascent
, s
->width
, font
->font
.height
);
448 code
= alloca (sizeof (FT_UInt
) * len
);
449 for (i
= 0; i
< len
; i
++)
450 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
451 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
453 XftDrawGlyphs (xftface_info
->xft_draw
, &fg
, xftfont_info
->xftfont
,
456 XftDrawSetClip (xftface_info
->xft_draw
, NULL
);
463 xftfont_anchor_point (font
, code
, index
, x
, y
)
469 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
470 FT_Face ft_face
= xftfont_info
->ft_face
;
472 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
474 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
476 if (index
>= ft_face
->glyph
->outline
.n_points
)
478 *x
= ft_face
->glyph
->outline
.points
[index
].x
;
479 *y
= ft_face
->glyph
->outline
.points
[index
].y
;
487 DEFSYM (Qxft
, "xft");
489 xftfont_driver
= ftfont_driver
;
490 xftfont_driver
.type
= Qxft
;
491 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
492 xftfont_driver
.list
= xftfont_list
;
493 xftfont_driver
.open
= xftfont_open
;
494 xftfont_driver
.close
= xftfont_close
;
495 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
496 xftfont_driver
.done_face
= xftfont_done_face
;
497 xftfont_driver
.encode_char
= xftfont_encode_char
;
498 xftfont_driver
.text_extents
= xftfont_text_extents
;
499 xftfont_driver
.draw
= xftfont_draw
;
500 xftfont_driver
.anchor_point
= xftfont_anchor_point
;
502 register_font_driver (&xftfont_driver
, NULL
);
505 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
506 (do not change this comment) */