1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008
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, 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"
40 /* Xft font driver. */
42 static Lisp_Object Qxft
;
44 /* The actual structure for Xft font that can be casted to struct
54 int maybe_otf
; /* Flag to tell if this may be OTF or not. */
56 #endif /* HAVE_LIBOTF */
59 /* Structure pointed by (struct face *)->extra */
63 XftColor xft_fg
; /* color for face->foreground */
64 XftColor xft_bg
; /* color for face->background */
67 static void xftfont_get_colors
P_ ((FRAME_PTR
, struct face
*, GC gc
,
68 struct xftface_info
*,
69 XftColor
*fg
, XftColor
*bg
));
72 /* Setup foreground and background colors of GC into FG and BG. If
73 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
77 xftfont_get_colors (f
, face
, gc
, xftface_info
, fg
, bg
)
81 struct xftface_info
*xftface_info
;
84 if (xftface_info
&& face
->gc
== gc
)
86 *fg
= xftface_info
->xft_fg
;
88 *bg
= xftface_info
->xft_bg
;
93 int fg_done
= 0, bg_done
= 0;
96 XGetGCValues (FRAME_X_DISPLAY (f
), gc
,
97 GCForeground
| GCBackground
, &xgcv
);
100 if (xgcv
.foreground
== face
->foreground
)
101 *fg
= xftface_info
->xft_fg
, fg_done
= 1;
102 else if (xgcv
.foreground
== face
->background
)
103 *fg
= xftface_info
->xft_bg
, fg_done
= 1;
106 else if (xgcv
.background
== face
->background
)
107 *bg
= xftface_info
->xft_bg
, bg_done
= 1;
108 else if (xgcv
.background
== face
->foreground
)
109 *bg
= xftface_info
->xft_fg
, bg_done
= 1;
112 if (fg_done
+ bg_done
< 2)
116 colors
[0].pixel
= fg
->pixel
= xgcv
.foreground
;
118 colors
[1].pixel
= bg
->pixel
= xgcv
.background
;
119 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
,
121 fg
->color
.alpha
= 0xFFFF;
122 fg
->color
.red
= colors
[0].red
;
123 fg
->color
.green
= colors
[0].green
;
124 fg
->color
.blue
= colors
[0].blue
;
127 bg
->color
.alpha
= 0xFFFF;
128 bg
->color
.red
= colors
[1].red
;
129 bg
->color
.green
= colors
[1].green
;
130 bg
->color
.blue
= colors
[1].blue
;
138 static Lisp_Object xftfont_list
P_ ((Lisp_Object
, Lisp_Object
));
139 static Lisp_Object xftfont_match
P_ ((Lisp_Object
, Lisp_Object
));
140 static struct font
*xftfont_open
P_ ((FRAME_PTR
, Lisp_Object
, int));
141 static void xftfont_close
P_ ((FRAME_PTR
, struct font
*));
142 static int xftfont_prepare_face
P_ ((FRAME_PTR
, struct face
*));
143 static void xftfont_done_face
P_ ((FRAME_PTR
, struct face
*));
144 static unsigned xftfont_encode_char
P_ ((struct font
*, int));
145 static int xftfont_text_extents
P_ ((struct font
*, unsigned *, int,
146 struct font_metrics
*));
147 static int xftfont_draw
P_ ((struct glyph_string
*, int, int, int, int, int));
149 static int xftfont_anchor_point
P_ ((struct font
*, unsigned, int,
151 static int xftfont_end_for_frame
P_ ((FRAME_PTR f
));
153 struct font_driver xftfont_driver
;
156 xftfont_list (frame
, spec
)
160 Lisp_Object val
= ftfont_driver
.list (frame
, spec
);
164 for (i
= 0; i
< ASIZE (val
); i
++)
165 ASET (AREF (val
, i
), FONT_TYPE_INDEX
, Qxft
);
170 xftfont_match (frame
, spec
)
174 Lisp_Object entity
= ftfont_driver
.match (frame
, spec
);
176 if (VECTORP (entity
))
177 ASET (entity
, FONT_TYPE_INDEX
, Qxft
);
181 extern Lisp_Object ftfont_font_format
P_ ((FcPattern
*));
183 static FcChar8 ascii_printable
[95];
186 xftfont_open (f
, entity
, pixel_size
)
191 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
192 Display
*display
= FRAME_X_DISPLAY (f
);
194 FcPattern
*pattern
, *pat
= NULL
;
196 struct xftfont_info
*xftfont_info
= NULL
;
197 XFontStruct
*xfont
= NULL
;
200 XftFont
*xftfont
= NULL
;
207 val
= AREF (entity
, FONT_EXTRA_INDEX
);
208 if (XTYPE (val
) != Lisp_Misc
209 || XMISCTYPE (val
) != Lisp_Misc_Save_Value
)
211 pattern
= XSAVE_VALUE (val
)->pointer
;
212 if (FcPatternGetString (pattern
, FC_FILE
, 0, &file
) != FcResultMatch
)
215 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 val
= AREF (entity
, FONT_FAMILY_INDEX
);
225 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
226 FcConfigSubstitute (NULL
, pat
, FcMatchPattern
);
229 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
230 xftfont
= XftFontOpenPattern (display
, pat
);
231 /* We should not destroy PAT here because it is kept in XFTFONT and
232 destroyed automatically when XFTFONT is closed. */
236 xftfont_info
= malloc (sizeof (struct xftfont_info
));
239 xfont
= malloc (sizeof (XFontStruct
));
242 xftfont_info
->display
= display
;
243 xftfont_info
->screen
= FRAME_X_SCREEN_NUMBER (f
);
244 xftfont_info
->xftfont
= xftfont
;
246 ft_face
= XftLockFace (xftfont
);
247 xftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
248 XftUnlockFace (xftfont
);
249 xftfont_info
->otf
= NULL
;
250 #endif /* HAVE_LIBOTF */
252 font
= (struct font
*) xftfont_info
;
253 font
->format
= ftfont_font_format (xftfont
->pattern
);
254 font
->entity
= entity
;
255 font
->pixel_size
= size
;
256 font
->driver
= &xftfont_driver
;
259 while (name
&& font_unparse_fcname (entity
, pixel_size
, name
, len
) < 0)
261 char *new = realloc (name
, len
+= 32);
269 font
->font
.full_name
= font
->font
.name
= name
;
270 font
->file_name
= (char *) file
;
271 font
->font
.size
= xftfont
->max_advance_width
;
272 font
->font
.charset
= font
->encoding_charset
= font
->repertory_charset
= -1;
274 if (FcPatternGetInteger (xftfont
->pattern
, FC_SPACING
, 0, &spacing
)
276 spacing
= FC_PROPORTIONAL
;
277 if (! ascii_printable
[0])
280 for (i
= 0; i
< 95; i
++)
281 ascii_printable
[i
] = ' ' + i
;
283 if (spacing
!= FC_PROPORTIONAL
)
285 font
->font
.average_width
= font
->font
.space_width
286 = xftfont
->max_advance_width
;
287 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
291 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
292 font
->font
.space_width
= extents
.xOff
;
293 if (font
->font
.space_width
<= 0)
294 /* dirty workaround */
295 font
->font
.space_width
= pixel_size
;
296 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
297 font
->font
.average_width
= (font
->font
.space_width
+ extents
.xOff
) / 95;
301 font
->ascent
= xftfont
->ascent
;
302 if (font
->ascent
< extents
.y
)
303 font
->ascent
= extents
.y
;
304 font
->descent
= xftfont
->descent
;
305 if (font
->descent
< extents
.height
- extents
.y
)
306 font
->descent
= extents
.height
- extents
.y
;
307 font
->font
.height
= font
->ascent
+ font
->descent
;
309 /* Unfortunately Xft doesn't provide a way to get minimum char
310 width. So, we use space_width instead. */
311 font
->min_width
= font
->font
.space_width
;
313 font
->font
.baseline_offset
= 0;
314 font
->font
.relative_compose
= 0;
315 font
->font
.default_ascent
= 0;
316 font
->font
.vertical_centering
= 0;
318 /* Setup pseudo XFontStruct */
320 xfont
->ascent
= font
->ascent
;
321 xfont
->descent
= font
->descent
;
322 xfont
->max_bounds
.descent
= font
->descent
;
323 xfont
->max_bounds
.width
= xftfont
->max_advance_width
;
324 xfont
->min_bounds
.width
= font
->font
.space_width
;
325 font
->font
.font
= xfont
;
329 /* Set global flag fonts_changed_p to non-zero if the font loaded
330 has a character with a smaller width than any other character
331 before, or if the font loaded has a smaller height than any other
332 font loaded before. If this happens, it will make a glyph matrix
333 reallocation necessary. */
334 if (dpyinfo
->n_fonts
== 1)
336 dpyinfo
->smallest_font_height
= font
->font
.height
;
337 dpyinfo
->smallest_char_width
= font
->min_width
;
342 if (dpyinfo
->smallest_font_height
> font
->font
.height
)
343 dpyinfo
->smallest_font_height
= font
->font
.height
,
344 fonts_changed_p
|= 1;
345 if (dpyinfo
->smallest_char_width
> font
->min_width
)
346 dpyinfo
->smallest_char_width
= font
->min_width
,
347 fonts_changed_p
|= 1;
353 if (xftfont
) XftFontClose (display
, xftfont
);
355 if (xftfont_info
) free (xftfont_info
);
356 if (xfont
) free (xfont
);
361 xftfont_close (f
, font
)
365 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
368 if (xftfont_info
->otf
)
369 OTF_close (xftfont_info
->otf
);
371 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
373 free (font
->font
.name
);
375 FRAME_X_DISPLAY_INFO (f
)->n_fonts
--;
379 xftfont_prepare_face (f
, face
)
383 struct xftface_info
*xftface_info
;
386 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
387 if (face
!= face
->ascii_face
)
389 face
->extra
= face
->ascii_face
->extra
;
394 xftface_info
= malloc (sizeof (struct xftface_info
));
399 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
400 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
403 face
->extra
= xftface_info
;
408 xftfont_done_face (f
, face
)
412 struct xftface_info
*xftface_info
;
415 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
416 if (face
!= face
->ascii_face
421 xftface_info
= (struct xftface_info
*) face
->extra
;
430 xftfont_encode_char (font
, c
)
434 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
435 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
438 return (code
? code
: FONT_INVALID_CODE
);
442 xftfont_text_extents (font
, code
, nglyphs
, metrics
)
446 struct font_metrics
*metrics
;
448 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
452 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
457 metrics
->lbearing
= - extents
.x
;
458 metrics
->rbearing
= - extents
.x
+ extents
.width
;
459 metrics
->width
= extents
.xOff
;
460 metrics
->ascent
= extents
.y
;
461 metrics
->descent
= extents
.height
- extents
.y
;
467 xftfont_get_xft_draw (f
)
470 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);;
475 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
478 FRAME_X_COLORMAP (f
));
482 font_put_frame_data (f
, &xftfont_driver
, xft_draw
);
488 xftfont_draw (s
, from
, to
, x
, y
, with_background
)
489 struct glyph_string
*s
;
490 int from
, to
, x
, y
, with_background
;
493 struct face
*face
= s
->face
;
494 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font_info
;
495 struct xftface_info
*xftface_info
= NULL
;
496 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
503 if (s
->font_info
== face
->font_info
)
504 xftface_info
= (struct xftface_info
*) face
->extra
;
505 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
506 &fg
, with_background
? &bg
: NULL
);
508 if (s
->num_clips
> 0)
509 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
511 XftDrawSetClip (xft_draw
, NULL
);
515 struct font
*font
= (struct font
*) face
->font_info
;
517 XftDrawRect (xft_draw
, &bg
,
518 x
, y
- face
->font
->ascent
, s
->width
, font
->font
.height
);
520 code
= alloca (sizeof (FT_UInt
) * len
);
521 for (i
= 0; i
< len
; i
++)
522 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
523 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
525 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
533 xftfont_anchor_point (font
, code
, index
, x
, y
)
539 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
540 FT_Face ft_face
= XftLockFace (xftfont_info
->xftfont
);
543 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
545 else if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
547 else if (index
>= ft_face
->glyph
->outline
.n_points
)
551 *x
= ft_face
->glyph
->outline
.points
[index
].x
;
552 *y
= ft_face
->glyph
->outline
.points
[index
].y
;
554 XftUnlockFace (xftfont_info
->xftfont
);
559 xftfont_end_for_frame (f
)
562 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
567 XftDrawDestroy (xft_draw
);
569 font_put_frame_data (f
, &xftfont_driver
, NULL
);
577 xftfont_shape (lgstring
)
578 Lisp_Object lgstring
;
581 struct xftfont_info
*xftfont_info
;
585 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
586 xftfont_info
= (struct xftfont_info
*) font
;
587 if (! xftfont_info
->maybe_otf
)
589 ft_face
= XftLockFace (xftfont_info
->xftfont
);
590 if (! xftfont_info
->otf
)
592 OTF
*otf
= OTF_open_ft_face (ft_face
);
594 if (! otf
|| OTF_get_table (otf
, "head") < 0)
598 xftfont_info
->maybe_otf
= 0;
599 XftUnlockFace (xftfont_info
->xftfont
);
602 xftfont_info
->otf
= otf
;
605 result
= ftfont_shape_by_flt (lgstring
, font
, ft_face
, xftfont_info
->otf
);
606 XftUnlockFace (xftfont_info
->xftfont
);
609 #endif /* HAVE_M17N_FLT */
610 #endif /* HAVE_LIBOTF */
615 DEFSYM (Qxft
, "xft");
617 xftfont_driver
= ftfont_driver
;
618 xftfont_driver
.type
= Qxft
;
619 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
620 xftfont_driver
.list
= xftfont_list
;
621 xftfont_driver
.match
= xftfont_match
;
622 xftfont_driver
.open
= xftfont_open
;
623 xftfont_driver
.close
= xftfont_close
;
624 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
625 xftfont_driver
.done_face
= xftfont_done_face
;
626 xftfont_driver
.encode_char
= xftfont_encode_char
;
627 xftfont_driver
.text_extents
= xftfont_text_extents
;
628 xftfont_driver
.draw
= xftfont_draw
;
629 xftfont_driver
.anchor_point
= xftfont_anchor_point
;
630 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
633 xftfont_driver
.shape
= xftfont_shape
;
634 #endif /* HAVE_M17N_FLT */
635 #endif /* HAVE_LIBOTF */
637 register_font_driver (&xftfont_driver
, NULL
);
640 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
641 (do not change this comment) */