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
->font
.charset
= font
->encoding_charset
= font
->repertory_charset
= -1;
265 font
->ascent
= xftfont
->ascent
;
266 font
->descent
= xftfont
->descent
;
267 font
->font
.height
= xftfont
->ascent
+ xftfont
->descent
;
269 if (FcPatternGetInteger (xftfont
->pattern
, FC_SPACING
, 0, &spacing
)
271 spacing
= FC_PROPORTIONAL
;
272 if (spacing
!= FC_PROPORTIONAL
)
273 font
->font
.average_width
= font
->font
.space_width
274 = xftfont
->max_advance_width
;
279 if (! ascii_printable
[0])
282 for (i
= 0; i
< 95; i
++)
283 ascii_printable
[i
] = ' ' + i
;
285 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
286 font
->font
.space_width
= extents
.xOff
;
287 if (font
->font
.space_width
<= 0)
288 /* dirty workaround */
289 font
->font
.space_width
= pixel_size
;
290 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
291 font
->font
.average_width
= (font
->font
.space_width
+ extents
.xOff
) / 95;
295 /* Unfortunately Xft doesn't provide a way to get minimum char
296 width. So, we use space_width instead. */
297 font
->min_width
= font
->font
.space_width
;
299 font
->font
.baseline_offset
= 0;
300 font
->font
.relative_compose
= 0;
301 font
->font
.default_ascent
= 0;
302 font
->font
.vertical_centering
= 0;
304 /* Setup pseudo XFontStruct */
305 xfont
->fid
= xftfont_default_fid (f
);
306 xfont
->ascent
= xftfont
->ascent
;
307 xfont
->descent
= xftfont
->descent
;
308 xfont
->max_bounds
.descent
= xftfont
->descent
;
309 xfont
->max_bounds
.width
= xftfont
->max_advance_width
;
310 xfont
->min_bounds
.width
= font
->font
.space_width
;
311 font
->font
.font
= xfont
;
315 /* Set global flag fonts_changed_p to non-zero if the font loaded
316 has a character with a smaller width than any other character
317 before, or if the font loaded has a smaller height than any other
318 font loaded before. If this happens, it will make a glyph matrix
319 reallocation necessary. */
320 if (dpyinfo
->n_fonts
== 1)
322 dpyinfo
->smallest_font_height
= font
->font
.height
;
323 dpyinfo
->smallest_char_width
= font
->min_width
;
328 if (dpyinfo
->smallest_font_height
> font
->font
.height
)
329 dpyinfo
->smallest_font_height
= font
->font
.height
,
330 fonts_changed_p
|= 1;
331 if (dpyinfo
->smallest_char_width
> font
->min_width
)
332 dpyinfo
->smallest_char_width
= font
->min_width
,
333 fonts_changed_p
|= 1;
339 if (xftfont
) XftFontClose (display
, xftfont
);
341 if (xftfont_info
) free (xftfont_info
);
342 if (xfont
) free (xfont
);
347 xftfont_close (f
, font
)
351 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
353 XftUnlockFace (xftfont_info
->xftfont
);
354 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
356 free (font
->font
.name
);
358 FRAME_X_DISPLAY_INFO (f
)->n_fonts
--;
362 xftfont_prepare_face (f
, face
)
366 struct xftface_info
*xftface_info
;
369 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
370 if (face
!= face
->ascii_face
)
372 face
->extra
= face
->ascii_face
->extra
;
377 xftface_info
= malloc (sizeof (struct xftface_info
));
382 xftface_info
->xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
385 FRAME_X_COLORMAP (f
));
386 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
387 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
390 face
->extra
= xftface_info
;
395 xftfont_done_face (f
, face
)
399 struct xftface_info
*xftface_info
;
402 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
403 if (face
!= face
->ascii_face
408 xftface_info
= (struct xftface_info
*) face
->extra
;
412 XftDrawDestroy (xftface_info
->xft_draw
);
420 xftfont_encode_char (font
, c
)
424 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
425 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
428 return (code
? code
: 0xFFFFFFFF);
432 xftfont_text_extents (font
, code
, nglyphs
, metrics
)
436 struct font_metrics
*metrics
;
438 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
442 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
447 metrics
->lbearing
= - extents
.x
;
448 metrics
->rbearing
= - extents
.x
+ extents
.width
;
449 metrics
->width
= extents
.xOff
;
450 metrics
->ascent
= extents
.y
;
451 metrics
->descent
= extents
.y
- extents
.height
;
457 xftfont_draw (s
, from
, to
, x
, y
, with_background
)
458 struct glyph_string
*s
;
459 int from
, to
, x
, y
, with_background
;
462 struct face
*face
= s
->face
;
463 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) face
->font_info
;
464 struct xftface_info
*xftface_info
= (struct xftface_info
*) face
->extra
;
471 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
472 &fg
, with_background
? &bg
: NULL
);
476 r
.x
= s
->clip_x
, r
.width
= s
->clip_width
;
477 r
.y
= s
->clip_y
, r
.height
= s
->clip_height
;
478 XftDrawSetClipRectangles (xftface_info
->xft_draw
, 0, 0, &r
, 1);
482 struct font
*font
= (struct font
*) face
->font_info
;
484 XftDrawRect (xftface_info
->xft_draw
, &bg
,
485 x
, y
- face
->font
->ascent
, s
->width
, font
->font
.height
);
487 code
= alloca (sizeof (FT_UInt
) * len
);
488 for (i
= 0; i
< len
; i
++)
489 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
490 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
492 XftDrawGlyphs (xftface_info
->xft_draw
, &fg
, xftfont_info
->xftfont
,
495 XftDrawSetClip (xftface_info
->xft_draw
, NULL
);
502 xftfont_anchor_point (font
, code
, index
, x
, y
)
508 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
509 FT_Face ft_face
= xftfont_info
->ft_face
;
511 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
513 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
515 if (index
>= ft_face
->glyph
->outline
.n_points
)
517 *x
= ft_face
->glyph
->outline
.points
[index
].x
;
518 *y
= ft_face
->glyph
->outline
.points
[index
].y
;
526 DEFSYM (Qxft
, "xft");
528 xftfont_driver
= ftfont_driver
;
529 xftfont_driver
.type
= Qxft
;
530 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
531 xftfont_driver
.list
= xftfont_list
;
532 xftfont_driver
.open
= xftfont_open
;
533 xftfont_driver
.close
= xftfont_close
;
534 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
535 xftfont_driver
.done_face
= xftfont_done_face
;
536 xftfont_driver
.encode_char
= xftfont_encode_char
;
537 xftfont_driver
.text_extents
= xftfont_text_extents
;
538 xftfont_driver
.draw
= xftfont_draw
;
539 xftfont_driver
.anchor_point
= xftfont_anchor_point
;
541 register_font_driver (&xftfont_driver
, NULL
);
544 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
545 (do not change this comment) */