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
= NULL
;
201 struct xftfont_info
*xftfont_info
= NULL
;
202 XFontStruct
*xfont
= NULL
;
205 XftFont
*xftfont
= NULL
;
210 val
= AREF (entity
, FONT_EXTRA_INDEX
);
211 if (XTYPE (val
) != Lisp_Misc
212 || XMISCTYPE (val
) != Lisp_Misc_Save_Value
)
214 pattern
= XSAVE_VALUE (val
)->pointer
;
215 if (FcPatternGetString (pattern
, FC_FILE
, 0, &file
) != FcResultMatch
)
218 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
222 pat
= FcPatternCreate ();
223 FcPatternAddString (pat
, FC_FILE
, file
);
224 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
225 FcPatternAddBool (pat
, FC_ANTIALIAS
, FcTrue
);
228 xftfont
= XftFontOpenPattern (display
, pat
);
229 /* We should not destroy PAT here because it is kept in XFTFONT and
230 destroyed automatically when XFTFONT is closed. */
234 xftfont_info
= malloc (sizeof (struct xftfont_info
));
237 xfont
= malloc (sizeof (XFontStruct
));
240 xftfont_info
->display
= display
;
241 xftfont_info
->screen
= FRAME_X_SCREEN_NUMBER (f
);
242 xftfont_info
->xftfont
= xftfont
;
243 xftfont_info
->ft_face
= XftLockFace (xftfont
);
245 font
= (struct font
*) xftfont_info
;
246 font
->entity
= entity
;
247 font
->pixel_size
= size
;
248 font
->driver
= &xftfont_driver
;
251 while (name
&& font_unparse_fcname (entity
, pixel_size
, name
, len
) < 0)
253 char *new = realloc (name
, len
+= 32);
261 font
->font
.full_name
= font
->font
.name
= name
;
262 font
->file_name
= (char *) file
;
263 font
->font
.size
= xftfont
->max_advance_width
;
264 font
->ascent
= xftfont
->ascent
;
265 font
->descent
= xftfont
->descent
;
266 font
->font
.height
= xftfont
->ascent
+ xftfont
->descent
;
268 if (FcPatternGetInteger (xftfont
->pattern
, FC_SPACING
, 0, &spacing
)
270 spacing
= FC_PROPORTIONAL
;
271 if (spacing
!= FC_PROPORTIONAL
)
272 font
->font
.average_width
= font
->font
.space_width
273 = xftfont
->max_advance_width
;
278 if (! ascii_printable
[0])
281 for (i
= 0; i
< 95; i
++)
282 ascii_printable
[i
] = ' ' + i
;
284 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
285 font
->font
.space_width
= extents
.xOff
;
286 if (font
->font
.space_width
<= 0)
287 /* dirty workaround */
288 font
->font
.space_width
= pixel_size
;
289 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
290 font
->font
.average_width
= (font
->font
.space_width
+ extents
.xOff
) / 95;
294 /* Unfortunately Xft doesn't provide a way to get minimum char
295 width. So, we use space_width instead. */
296 font
->min_width
= font
->font
.space_width
;
298 font
->font
.baseline_offset
= 0;
299 font
->font
.relative_compose
= 0;
300 font
->font
.default_ascent
= 0;
301 font
->font
.vertical_centering
= 0;
303 /* Setup pseudo XFontStruct */
304 xfont
->fid
= xftfont_default_fid (f
);
305 xfont
->ascent
= xftfont
->ascent
;
306 xfont
->descent
= xftfont
->descent
;
307 xfont
->max_bounds
.descent
= xftfont
->descent
;
308 xfont
->max_bounds
.width
= xftfont
->max_advance_width
;
309 xfont
->min_bounds
.width
= font
->font
.space_width
;
310 font
->font
.font
= xfont
;
314 /* Set global flag fonts_changed_p to non-zero if the font loaded
315 has a character with a smaller width than any other character
316 before, or if the font loaded has a smaller height than any other
317 font loaded before. If this happens, it will make a glyph matrix
318 reallocation necessary. */
319 if (dpyinfo
->n_fonts
== 1)
321 dpyinfo
->smallest_font_height
= font
->font
.height
;
322 dpyinfo
->smallest_char_width
= font
->min_width
;
327 if (dpyinfo
->smallest_font_height
> font
->font
.height
)
328 dpyinfo
->smallest_font_height
= font
->font
.height
,
329 fonts_changed_p
|= 1;
330 if (dpyinfo
->smallest_char_width
> font
->min_width
)
331 dpyinfo
->smallest_char_width
= font
->min_width
,
332 fonts_changed_p
|= 1;
338 if (xftfont
) XftFontClose (display
, xftfont
);
340 if (xftfont_info
) free (xftfont_info
);
341 if (xfont
) free (xfont
);
346 xftfont_close (f
, font
)
350 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
352 XftUnlockFace (xftfont_info
->xftfont
);
353 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
355 free (font
->font
.name
);
357 FRAME_X_DISPLAY_INFO (f
)->n_fonts
--;
361 xftfont_prepare_face (f
, face
)
365 struct xftface_info
*xftface_info
= malloc (sizeof (struct xftface_info
));
371 xftface_info
->xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
374 FRAME_X_COLORMAP (f
));
375 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
376 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
379 face
->extra
= xftface_info
;
384 xftfont_done_face (f
, face
)
388 struct xftface_info
*xftface_info
= (struct xftface_info
*) face
->extra
;
393 XftDrawDestroy (xftface_info
->xft_draw
);
401 xftfont_encode_char (font
, c
)
405 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
406 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
409 return (code
? code
: 0xFFFFFFFF);
413 xftfont_text_extents (font
, code
, nglyphs
, metrics
)
417 struct font_metrics
*metrics
;
419 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
423 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
428 metrics
->lbearing
= - extents
.x
;
429 metrics
->rbearing
= - extents
.x
+ extents
.width
;
430 metrics
->width
= extents
.xOff
;
431 metrics
->ascent
= extents
.y
;
432 metrics
->descent
= extents
.y
- extents
.height
;
438 xftfont_draw (s
, from
, to
, x
, y
, with_background
)
439 struct glyph_string
*s
;
440 int from
, to
, x
, y
, with_background
;
443 struct face
*face
= s
->face
;
444 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) face
->font_info
;
445 struct xftface_info
*xftface_info
= (struct xftface_info
*) face
->extra
;
452 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
453 &fg
, with_background
? &bg
: NULL
);
457 r
.x
= s
->clip_x
, r
.width
= s
->clip_width
;
458 r
.y
= s
->clip_y
, r
.height
= s
->clip_height
;
459 XftDrawSetClipRectangles (xftface_info
->xft_draw
, 0, 0, &r
, 1);
463 struct font
*font
= (struct font
*) face
->font_info
;
465 XftDrawRect (xftface_info
->xft_draw
, &bg
,
466 x
, y
- face
->font
->ascent
, s
->width
, font
->font
.height
);
468 code
= alloca (sizeof (FT_UInt
) * len
);
469 for (i
= 0; i
< len
; i
++)
470 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
471 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
473 XftDrawGlyphs (xftface_info
->xft_draw
, &fg
, xftfont_info
->xftfont
,
476 XftDrawSetClip (xftface_info
->xft_draw
, NULL
);
483 xftfont_anchor_point (font
, code
, index
, x
, y
)
489 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
490 FT_Face ft_face
= xftfont_info
->ft_face
;
492 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
494 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
496 if (index
>= ft_face
->glyph
->outline
.n_points
)
498 *x
= ft_face
->glyph
->outline
.points
[index
].x
;
499 *y
= ft_face
->glyph
->outline
.points
[index
].y
;
507 DEFSYM (Qxft
, "xft");
509 xftfont_driver
= ftfont_driver
;
510 xftfont_driver
.type
= Qxft
;
511 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
512 xftfont_driver
.list
= xftfont_list
;
513 xftfont_driver
.open
= xftfont_open
;
514 xftfont_driver
.close
= xftfont_close
;
515 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
516 xftfont_driver
.done_face
= xftfont_done_face
;
517 xftfont_driver
.encode_char
= xftfont_encode_char
;
518 xftfont_driver
.text_extents
= xftfont_text_extents
;
519 xftfont_driver
.draw
= xftfont_draw
;
520 xftfont_driver
.anchor_point
= xftfont_anchor_point
;
522 register_font_driver (&xftfont_driver
, NULL
);
525 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
526 (do not change this comment) */