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
52 FT_Face ft_face
; /* set to XftLockFace (xftfont) */
55 /* Structure pointed by (struct face *)->extra */
59 XftColor xft_fg
; /* color for face->foreground */
60 XftColor xft_bg
; /* color for face->background */
64 static void xftfont_get_colors
P_ ((FRAME_PTR
, struct face
*, GC gc
,
65 struct xftface_info
*,
66 XftColor
*fg
, XftColor
*bg
));
67 static Font xftfont_default_fid
P_ ((FRAME_PTR
));
70 /* Setup foreground and background colors of GC into FG and BG. If
71 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
75 xftfont_get_colors (f
, face
, gc
, xftface_info
, fg
, bg
)
79 struct xftface_info
*xftface_info
;
82 if (xftface_info
&& face
->gc
== gc
)
84 *fg
= xftface_info
->xft_fg
;
86 *bg
= xftface_info
->xft_bg
;
91 int fg_done
= 0, bg_done
= 0;
94 XGetGCValues (FRAME_X_DISPLAY (f
), gc
,
95 GCForeground
| GCBackground
, &xgcv
);
98 if (xgcv
.foreground
== face
->foreground
)
99 *fg
= xftface_info
->xft_fg
, fg_done
= 1;
100 else if (xgcv
.foreground
== face
->background
)
101 *fg
= xftface_info
->xft_bg
, fg_done
= 1;
104 else if (xgcv
.background
== face
->background
)
105 *bg
= xftface_info
->xft_bg
, bg_done
= 1;
106 else if (xgcv
.background
== face
->foreground
)
107 *bg
= xftface_info
->xft_fg
, bg_done
= 1;
110 if (fg_done
+ bg_done
< 2)
114 colors
[0].pixel
= fg
->pixel
= xgcv
.foreground
;
116 colors
[1].pixel
= bg
->pixel
= xgcv
.background
;
117 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
,
119 fg
->color
.alpha
= 0xFFFF;
120 fg
->color
.red
= colors
[0].red
;
121 fg
->color
.green
= colors
[0].green
;
122 fg
->color
.blue
= colors
[0].blue
;
125 bg
->color
.alpha
= 0xFFFF;
126 bg
->color
.red
= colors
[1].red
;
127 bg
->color
.green
= colors
[1].green
;
128 bg
->color
.blue
= colors
[1].blue
;
135 /* Return the default Font ID on frame F. The Returned Font ID is
136 stored in the GC of the frame F, but the font is never used. So,
137 any ID is ok as long as it is valid. */
140 xftfont_default_fid (f
)
143 static int fid_known
;
148 fid
= XLoadFont (FRAME_X_DISPLAY (f
), "fixed");
151 fid
= XLoadFont (FRAME_X_DISPLAY (f
), "*");
161 static Lisp_Object xftfont_list
P_ ((Lisp_Object
, Lisp_Object
));
162 static Lisp_Object xftfont_match
P_ ((Lisp_Object
, Lisp_Object
));
163 static struct font
*xftfont_open
P_ ((FRAME_PTR
, Lisp_Object
, int));
164 static void xftfont_close
P_ ((FRAME_PTR
, struct font
*));
165 static int xftfont_prepare_face
P_ ((FRAME_PTR
, struct face
*));
166 static void xftfont_done_face
P_ ((FRAME_PTR
, struct face
*));
167 static unsigned xftfont_encode_char
P_ ((struct font
*, int));
168 static int xftfont_text_extents
P_ ((struct font
*, unsigned *, int,
169 struct font_metrics
*));
170 static int xftfont_draw
P_ ((struct glyph_string
*, int, int, int, int, int));
172 static int xftfont_anchor_point
P_ ((struct font
*, unsigned, int,
175 struct font_driver xftfont_driver
;
178 xftfont_list (frame
, spec
)
182 Lisp_Object val
= ftfont_driver
.list (frame
, spec
);
186 for (i
= 0; i
< ASIZE (val
); i
++)
187 ASET (AREF (val
, i
), FONT_TYPE_INDEX
, Qxft
);
192 xftfont_match (frame
, spec
)
196 Lisp_Object entity
= ftfont_driver
.match (frame
, spec
);
198 if (VECTORP (entity
))
199 ASET (entity
, FONT_TYPE_INDEX
, Qxft
);
203 extern Lisp_Object ftfont_font_format
P_ ((FcPattern
*));
205 static FcChar8 ascii_printable
[95];
208 xftfont_open (f
, entity
, pixel_size
)
213 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
214 Display
*display
= FRAME_X_DISPLAY (f
);
216 FcPattern
*pattern
, *pat
= NULL
;
218 struct xftfont_info
*xftfont_info
= NULL
;
219 XFontStruct
*xfont
= NULL
;
222 XftFont
*xftfont
= NULL
;
228 val
= AREF (entity
, FONT_EXTRA_INDEX
);
229 if (XTYPE (val
) != Lisp_Misc
230 || XMISCTYPE (val
) != Lisp_Misc_Save_Value
)
232 pattern
= XSAVE_VALUE (val
)->pointer
;
233 if (FcPatternGetString (pattern
, FC_FILE
, 0, &file
) != FcResultMatch
)
236 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
240 pat
= FcPatternCreate ();
241 FcPatternAddString (pat
, FC_FILE
, file
);
242 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
243 /*FcPatternAddBool (pat, FC_ANTIALIAS, FcTrue);*/
244 val
= AREF (entity
, FONT_FAMILY_INDEX
);
246 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
247 FcConfigSubstitute (NULL
, pat
, FcMatchPattern
);
250 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
251 xftfont
= XftFontOpenPattern (display
, pat
);
252 /* We should not destroy PAT here because it is kept in XFTFONT and
253 destroyed automatically when XFTFONT is closed. */
257 xftfont_info
= malloc (sizeof (struct xftfont_info
));
260 xfont
= malloc (sizeof (XFontStruct
));
263 xftfont_info
->display
= display
;
264 xftfont_info
->screen
= FRAME_X_SCREEN_NUMBER (f
);
265 xftfont_info
->xftfont
= xftfont
;
266 xftfont_info
->ft_face
= XftLockFace (xftfont
);
268 font
= (struct font
*) xftfont_info
;
269 font
->format
= ftfont_font_format (xftfont
->pattern
);
270 font
->entity
= entity
;
271 font
->pixel_size
= size
;
272 font
->driver
= &xftfont_driver
;
275 while (name
&& font_unparse_fcname (entity
, pixel_size
, name
, len
) < 0)
277 char *new = realloc (name
, len
+= 32);
285 font
->font
.full_name
= font
->font
.name
= name
;
286 font
->file_name
= (char *) file
;
287 font
->font
.size
= xftfont
->max_advance_width
;
288 font
->font
.charset
= font
->encoding_charset
= font
->repertory_charset
= -1;
290 if (FcPatternGetInteger (xftfont
->pattern
, FC_SPACING
, 0, &spacing
)
292 spacing
= FC_PROPORTIONAL
;
293 if (! ascii_printable
[0])
296 for (i
= 0; i
< 95; i
++)
297 ascii_printable
[i
] = ' ' + i
;
299 if (spacing
!= FC_PROPORTIONAL
)
301 font
->font
.average_width
= font
->font
.space_width
302 = xftfont
->max_advance_width
;
303 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
307 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
308 font
->font
.space_width
= extents
.xOff
;
309 if (font
->font
.space_width
<= 0)
310 /* dirty workaround */
311 font
->font
.space_width
= pixel_size
;
312 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
313 font
->font
.average_width
= (font
->font
.space_width
+ extents
.xOff
) / 95;
317 font
->ascent
= xftfont
->ascent
;
318 if (font
->ascent
< extents
.y
)
319 font
->ascent
= extents
.y
;
320 font
->descent
= xftfont
->descent
;
321 if (font
->descent
< extents
.height
- extents
.y
)
322 font
->descent
= extents
.height
- extents
.y
;
323 font
->font
.height
= font
->ascent
+ font
->descent
;
325 /* Unfortunately Xft doesn't provide a way to get minimum char
326 width. So, we use space_width instead. */
327 font
->min_width
= font
->font
.space_width
;
329 font
->font
.baseline_offset
= 0;
330 font
->font
.relative_compose
= 0;
331 font
->font
.default_ascent
= 0;
332 font
->font
.vertical_centering
= 0;
334 /* Setup pseudo XFontStruct */
335 xfont
->fid
= xftfont_default_fid (f
);
336 xfont
->ascent
= font
->ascent
;
337 xfont
->descent
= font
->descent
;
338 xfont
->max_bounds
.descent
= font
->descent
;
339 xfont
->max_bounds
.width
= xftfont
->max_advance_width
;
340 xfont
->min_bounds
.width
= font
->font
.space_width
;
341 font
->font
.font
= xfont
;
345 /* Set global flag fonts_changed_p to non-zero if the font loaded
346 has a character with a smaller width than any other character
347 before, or if the font loaded has a smaller height than any other
348 font loaded before. If this happens, it will make a glyph matrix
349 reallocation necessary. */
350 if (dpyinfo
->n_fonts
== 1)
352 dpyinfo
->smallest_font_height
= font
->font
.height
;
353 dpyinfo
->smallest_char_width
= font
->min_width
;
358 if (dpyinfo
->smallest_font_height
> font
->font
.height
)
359 dpyinfo
->smallest_font_height
= font
->font
.height
,
360 fonts_changed_p
|= 1;
361 if (dpyinfo
->smallest_char_width
> font
->min_width
)
362 dpyinfo
->smallest_char_width
= font
->min_width
,
363 fonts_changed_p
|= 1;
369 if (xftfont
) XftFontClose (display
, xftfont
);
371 if (xftfont_info
) free (xftfont_info
);
372 if (xfont
) free (xfont
);
377 xftfont_close (f
, font
)
381 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
383 XftUnlockFace (xftfont_info
->xftfont
);
384 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
386 free (font
->font
.name
);
388 FRAME_X_DISPLAY_INFO (f
)->n_fonts
--;
392 xftfont_prepare_face (f
, face
)
396 struct xftface_info
*xftface_info
;
399 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
400 if (face
!= face
->ascii_face
)
402 face
->extra
= face
->ascii_face
->extra
;
407 xftface_info
= malloc (sizeof (struct xftface_info
));
412 xftface_info
->xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
415 FRAME_X_COLORMAP (f
));
416 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
417 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
420 face
->extra
= xftface_info
;
425 xftfont_done_face (f
, face
)
429 struct xftface_info
*xftface_info
;
432 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
433 if (face
!= face
->ascii_face
438 xftface_info
= (struct xftface_info
*) face
->extra
;
442 XftDrawDestroy (xftface_info
->xft_draw
);
450 xftfont_encode_char (font
, c
)
454 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
455 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
458 return (code
? code
: 0xFFFFFFFF);
462 xftfont_text_extents (font
, code
, nglyphs
, metrics
)
466 struct font_metrics
*metrics
;
468 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
472 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
477 metrics
->lbearing
= - extents
.x
;
478 metrics
->rbearing
= - extents
.x
+ extents
.width
;
479 metrics
->width
= extents
.xOff
;
480 metrics
->ascent
= extents
.y
;
481 metrics
->descent
= extents
.height
- extents
.y
;
487 xftfont_draw (s
, from
, to
, x
, y
, with_background
)
488 struct glyph_string
*s
;
489 int from
, to
, x
, y
, with_background
;
492 struct face
*face
= s
->face
;
493 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font_info
;
494 struct xftface_info
*xftface_info
= NULL
;
495 XftDraw
*xft_draw
= NULL
;
502 if (s
->font_info
== face
->font_info
)
504 xftface_info
= (struct xftface_info
*) face
->extra
;
505 xft_draw
= xftface_info
->xft_draw
;
507 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
508 &fg
, with_background
? &bg
: NULL
);
511 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
514 FRAME_X_COLORMAP (f
));
517 r
.x
= s
->clip_x
, r
.width
= s
->clip_width
;
518 r
.y
= s
->clip_y
, r
.height
= s
->clip_height
;
519 XftDrawSetClipRectangles (xft_draw
, 0, 0, &r
, 1);
523 struct font
*font
= (struct font
*) face
->font_info
;
525 XftDrawRect (xft_draw
, &bg
,
526 x
, y
- face
->font
->ascent
, s
->width
, font
->font
.height
);
528 code
= alloca (sizeof (FT_UInt
) * len
);
529 for (i
= 0; i
< len
; i
++)
530 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
531 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
533 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
536 XftDrawSetClip (xft_draw
, NULL
);
537 if (s
->font_info
!= face
->font_info
)
538 XftDrawDestroy (xft_draw
);
545 xftfont_anchor_point (font
, code
, index
, x
, y
)
551 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
552 FT_Face ft_face
= xftfont_info
->ft_face
;
554 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
556 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
558 if (index
>= ft_face
->glyph
->outline
.n_points
)
560 *x
= ft_face
->glyph
->outline
.points
[index
].x
;
561 *y
= ft_face
->glyph
->outline
.points
[index
].y
;
569 DEFSYM (Qxft
, "xft");
571 xftfont_driver
= ftfont_driver
;
572 xftfont_driver
.type
= Qxft
;
573 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
574 xftfont_driver
.list
= xftfont_list
;
575 xftfont_driver
.match
= xftfont_match
;
576 xftfont_driver
.open
= xftfont_open
;
577 xftfont_driver
.close
= xftfont_close
;
578 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
579 xftfont_driver
.done_face
= xftfont_done_face
;
580 xftfont_driver
.encode_char
= xftfont_encode_char
;
581 xftfont_driver
.text_extents
= xftfont_text_extents
;
582 xftfont_driver
.draw
= xftfont_draw
;
583 xftfont_driver
.anchor_point
= xftfont_anchor_point
;
585 register_font_driver (&xftfont_driver
, NULL
);
588 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
589 (do not change this comment) */