1 /* xftfont.c -- XFT font driver.
2 Copyright (C) 2006 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007
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"
40 /* Xft font driver. */
42 static Lisp_Object Qxft
;
44 /* The actual structure for Xft font that can be casted to struct
53 FT_Face ft_face
; /* Set to the value of XftLockFace (xftfont). */
55 int maybe_otf
; /* Flag to tell if this may be OTF or not. */
57 #endif /* HAVE_LIBOTF */
60 /* Structure pointed by (struct face *)->extra */
64 XftColor xft_fg
; /* color for face->foreground */
65 XftColor xft_bg
; /* color for face->background */
68 static void xftfont_get_colors
P_ ((FRAME_PTR
, struct face
*, GC gc
,
69 struct xftface_info
*,
70 XftColor
*fg
, XftColor
*bg
));
71 static Font xftfont_default_fid
P_ ((FRAME_PTR
));
74 /* Setup foreground and background colors of GC into FG and BG. If
75 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
79 xftfont_get_colors (f
, face
, gc
, xftface_info
, fg
, bg
)
83 struct xftface_info
*xftface_info
;
86 if (xftface_info
&& face
->gc
== gc
)
88 *fg
= xftface_info
->xft_fg
;
90 *bg
= xftface_info
->xft_bg
;
95 int fg_done
= 0, bg_done
= 0;
98 XGetGCValues (FRAME_X_DISPLAY (f
), gc
,
99 GCForeground
| GCBackground
, &xgcv
);
102 if (xgcv
.foreground
== face
->foreground
)
103 *fg
= xftface_info
->xft_fg
, fg_done
= 1;
104 else if (xgcv
.foreground
== face
->background
)
105 *fg
= xftface_info
->xft_bg
, fg_done
= 1;
108 else if (xgcv
.background
== face
->background
)
109 *bg
= xftface_info
->xft_bg
, bg_done
= 1;
110 else if (xgcv
.background
== face
->foreground
)
111 *bg
= xftface_info
->xft_fg
, bg_done
= 1;
114 if (fg_done
+ bg_done
< 2)
118 colors
[0].pixel
= fg
->pixel
= xgcv
.foreground
;
120 colors
[1].pixel
= bg
->pixel
= xgcv
.background
;
121 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
,
123 fg
->color
.alpha
= 0xFFFF;
124 fg
->color
.red
= colors
[0].red
;
125 fg
->color
.green
= colors
[0].green
;
126 fg
->color
.blue
= colors
[0].blue
;
129 bg
->color
.alpha
= 0xFFFF;
130 bg
->color
.red
= colors
[1].red
;
131 bg
->color
.green
= colors
[1].green
;
132 bg
->color
.blue
= colors
[1].blue
;
139 /* Return the default Font ID on frame F. The Returned Font ID is
140 stored in the GC of the frame F, but the font is never used. So,
141 any ID is ok as long as it is valid. */
144 xftfont_default_fid (f
)
147 static int fid_known
;
152 fid
= XLoadFont (FRAME_X_DISPLAY (f
), "fixed");
155 fid
= XLoadFont (FRAME_X_DISPLAY (f
), "*");
165 static Lisp_Object xftfont_list
P_ ((Lisp_Object
, Lisp_Object
));
166 static Lisp_Object xftfont_match
P_ ((Lisp_Object
, Lisp_Object
));
167 static struct font
*xftfont_open
P_ ((FRAME_PTR
, Lisp_Object
, int));
168 static void xftfont_close
P_ ((FRAME_PTR
, struct font
*));
169 static int xftfont_prepare_face
P_ ((FRAME_PTR
, struct face
*));
170 static void xftfont_done_face
P_ ((FRAME_PTR
, struct face
*));
171 static unsigned xftfont_encode_char
P_ ((struct font
*, int));
172 static int xftfont_text_extents
P_ ((struct font
*, unsigned *, int,
173 struct font_metrics
*));
174 static int xftfont_draw
P_ ((struct glyph_string
*, int, int, int, int, int));
176 static int xftfont_anchor_point
P_ ((struct font
*, unsigned, int,
178 static int xftfont_start_for_frame
P_ ((FRAME_PTR f
));
179 static int xftfont_end_for_frame
P_ ((FRAME_PTR f
));
181 struct font_driver xftfont_driver
;
184 xftfont_list (frame
, spec
)
188 Lisp_Object val
= ftfont_driver
.list (frame
, spec
);
192 for (i
= 0; i
< ASIZE (val
); i
++)
193 ASET (AREF (val
, i
), FONT_TYPE_INDEX
, Qxft
);
198 xftfont_match (frame
, spec
)
202 Lisp_Object entity
= ftfont_driver
.match (frame
, spec
);
204 if (VECTORP (entity
))
205 ASET (entity
, FONT_TYPE_INDEX
, Qxft
);
209 extern Lisp_Object ftfont_font_format
P_ ((FcPattern
*));
211 static FcChar8 ascii_printable
[95];
214 xftfont_open (f
, entity
, pixel_size
)
219 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
220 Display
*display
= FRAME_X_DISPLAY (f
);
222 FcPattern
*pattern
, *pat
= NULL
;
224 struct xftfont_info
*xftfont_info
= NULL
;
225 XFontStruct
*xfont
= NULL
;
228 XftFont
*xftfont
= NULL
;
234 val
= AREF (entity
, FONT_EXTRA_INDEX
);
235 if (XTYPE (val
) != Lisp_Misc
236 || XMISCTYPE (val
) != Lisp_Misc_Save_Value
)
238 pattern
= XSAVE_VALUE (val
)->pointer
;
239 if (FcPatternGetString (pattern
, FC_FILE
, 0, &file
) != FcResultMatch
)
242 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
246 pat
= FcPatternCreate ();
247 FcPatternAddString (pat
, FC_FILE
, file
);
248 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
249 /*FcPatternAddBool (pat, FC_ANTIALIAS, FcTrue);*/
250 val
= AREF (entity
, FONT_FAMILY_INDEX
);
252 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
253 FcConfigSubstitute (NULL
, pat
, FcMatchPattern
);
256 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
257 xftfont
= XftFontOpenPattern (display
, pat
);
258 /* We should not destroy PAT here because it is kept in XFTFONT and
259 destroyed automatically when XFTFONT is closed. */
263 xftfont_info
= malloc (sizeof (struct xftfont_info
));
266 xfont
= malloc (sizeof (XFontStruct
));
269 xftfont_info
->display
= display
;
270 xftfont_info
->screen
= FRAME_X_SCREEN_NUMBER (f
);
271 xftfont_info
->xftfont
= xftfont
;
272 xftfont_info
->ft_face
= XftLockFace (xftfont
);
274 xftfont_info
->maybe_otf
= xftfont_info
->ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
275 xftfont_info
->otf
= NULL
;
276 #endif /* HAVE_LIBOTF */
278 font
= (struct font
*) xftfont_info
;
279 font
->format
= ftfont_font_format (xftfont
->pattern
);
280 font
->entity
= entity
;
281 font
->pixel_size
= size
;
282 font
->driver
= &xftfont_driver
;
285 while (name
&& font_unparse_fcname (entity
, pixel_size
, name
, len
) < 0)
287 char *new = realloc (name
, len
+= 32);
295 font
->font
.full_name
= font
->font
.name
= name
;
296 font
->file_name
= (char *) file
;
297 font
->font
.size
= xftfont
->max_advance_width
;
298 font
->font
.charset
= font
->encoding_charset
= font
->repertory_charset
= -1;
300 if (FcPatternGetInteger (xftfont
->pattern
, FC_SPACING
, 0, &spacing
)
302 spacing
= FC_PROPORTIONAL
;
303 if (! ascii_printable
[0])
306 for (i
= 0; i
< 95; i
++)
307 ascii_printable
[i
] = ' ' + i
;
309 if (spacing
!= FC_PROPORTIONAL
)
311 font
->font
.average_width
= font
->font
.space_width
312 = xftfont
->max_advance_width
;
313 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
317 XftTextExtents8 (display
, xftfont
, ascii_printable
, 1, &extents
);
318 font
->font
.space_width
= extents
.xOff
;
319 if (font
->font
.space_width
<= 0)
320 /* dirty workaround */
321 font
->font
.space_width
= pixel_size
;
322 XftTextExtents8 (display
, xftfont
, ascii_printable
+ 1, 94, &extents
);
323 font
->font
.average_width
= (font
->font
.space_width
+ extents
.xOff
) / 95;
327 font
->ascent
= xftfont
->ascent
;
328 if (font
->ascent
< extents
.y
)
329 font
->ascent
= extents
.y
;
330 font
->descent
= xftfont
->descent
;
331 if (font
->descent
< extents
.height
- extents
.y
)
332 font
->descent
= extents
.height
- extents
.y
;
333 font
->font
.height
= font
->ascent
+ font
->descent
;
335 /* Unfortunately Xft doesn't provide a way to get minimum char
336 width. So, we use space_width instead. */
337 font
->min_width
= font
->font
.space_width
;
339 font
->font
.baseline_offset
= 0;
340 font
->font
.relative_compose
= 0;
341 font
->font
.default_ascent
= 0;
342 font
->font
.vertical_centering
= 0;
344 /* Setup pseudo XFontStruct */
345 xfont
->fid
= xftfont_default_fid (f
);
346 xfont
->ascent
= font
->ascent
;
347 xfont
->descent
= font
->descent
;
348 xfont
->max_bounds
.descent
= font
->descent
;
349 xfont
->max_bounds
.width
= xftfont
->max_advance_width
;
350 xfont
->min_bounds
.width
= font
->font
.space_width
;
351 font
->font
.font
= xfont
;
355 /* Set global flag fonts_changed_p to non-zero if the font loaded
356 has a character with a smaller width than any other character
357 before, or if the font loaded has a smaller height than any other
358 font loaded before. If this happens, it will make a glyph matrix
359 reallocation necessary. */
360 if (dpyinfo
->n_fonts
== 1)
362 dpyinfo
->smallest_font_height
= font
->font
.height
;
363 dpyinfo
->smallest_char_width
= font
->min_width
;
368 if (dpyinfo
->smallest_font_height
> font
->font
.height
)
369 dpyinfo
->smallest_font_height
= font
->font
.height
,
370 fonts_changed_p
|= 1;
371 if (dpyinfo
->smallest_char_width
> font
->min_width
)
372 dpyinfo
->smallest_char_width
= font
->min_width
,
373 fonts_changed_p
|= 1;
379 if (xftfont
) XftFontClose (display
, xftfont
);
381 if (xftfont_info
) free (xftfont_info
);
382 if (xfont
) free (xfont
);
387 xftfont_close (f
, font
)
391 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
394 if (xftfont_info
->otf
)
395 OTF_close (xftfont_info
->otf
);
397 XftUnlockFace (xftfont_info
->xftfont
);
398 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
400 free (font
->font
.name
);
402 FRAME_X_DISPLAY_INFO (f
)->n_fonts
--;
406 xftfont_prepare_face (f
, face
)
410 struct xftface_info
*xftface_info
;
413 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
414 if (face
!= face
->ascii_face
)
416 face
->extra
= face
->ascii_face
->extra
;
421 xftface_info
= malloc (sizeof (struct xftface_info
));
426 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
427 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
430 face
->extra
= xftface_info
;
435 xftfont_done_face (f
, face
)
439 struct xftface_info
*xftface_info
;
442 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
443 if (face
!= face
->ascii_face
448 xftface_info
= (struct xftface_info
*) face
->extra
;
457 xftfont_encode_char (font
, c
)
461 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
462 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
465 return (code
? code
: 0xFFFFFFFF);
469 xftfont_text_extents (font
, code
, nglyphs
, metrics
)
473 struct font_metrics
*metrics
;
475 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
479 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
484 metrics
->lbearing
= - extents
.x
;
485 metrics
->rbearing
= - extents
.x
+ extents
.width
;
486 metrics
->width
= extents
.xOff
;
487 metrics
->ascent
= extents
.y
;
488 metrics
->descent
= extents
.height
- extents
.y
;
494 xftfont_get_xft_draw (f
)
497 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);;
502 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
505 FRAME_X_COLORMAP (f
));
509 font_put_frame_data (f
, &xftfont_driver
, xft_draw
);
515 xftfont_draw (s
, from
, to
, x
, y
, with_background
)
516 struct glyph_string
*s
;
517 int from
, to
, x
, y
, with_background
;
520 struct face
*face
= s
->face
;
521 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font_info
;
522 struct xftface_info
*xftface_info
= NULL
;
523 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
530 if (s
->font_info
== face
->font_info
)
531 xftface_info
= (struct xftface_info
*) face
->extra
;
532 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
533 &fg
, with_background
? &bg
: NULL
);
535 if (s
->num_clips
> 0)
536 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
538 XftDrawSetClip (xft_draw
, NULL
);
542 struct font
*font
= (struct font
*) face
->font_info
;
544 XftDrawRect (xft_draw
, &bg
,
545 x
, y
- face
->font
->ascent
, s
->width
, font
->font
.height
);
547 code
= alloca (sizeof (FT_UInt
) * len
);
548 for (i
= 0; i
< len
; i
++)
549 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
550 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
552 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
560 xftfont_anchor_point (font
, code
, index
, x
, y
)
566 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
567 FT_Face ft_face
= xftfont_info
->ft_face
;
569 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
571 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
573 if (index
>= ft_face
->glyph
->outline
.n_points
)
575 *x
= ft_face
->glyph
->outline
.points
[index
].x
;
576 *y
= ft_face
->glyph
->outline
.points
[index
].y
;
581 xftfont_end_for_frame (f
)
584 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
589 XftDrawDestroy (xft_draw
);
591 font_put_frame_data (f
, &xftfont_driver
, NULL
);
599 xftfont_shape (lgstring
)
600 Lisp_Object lgstring
;
603 struct xftfont_info
*xftfont_info
;
605 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
606 xftfont_info
= (struct xftfont_info
*) font
;
607 if (! xftfont_info
->maybe_otf
)
609 if (! xftfont_info
->otf
)
611 OTF
*otf
= OTF_open_ft_face (xftfont_info
->ft_face
);
613 if (! otf
|| OTF_get_table (otf
, "head") < 0)
617 xftfont_info
->maybe_otf
= 0;
620 xftfont_info
->otf
= otf
;
623 return ftfont_shape_by_flt (lgstring
, font
, xftfont_info
->ft_face
,
626 #endif /* HAVE_M17N_FLT */
627 #endif /* HAVE_LIBOTF */
632 DEFSYM (Qxft
, "xft");
634 xftfont_driver
= ftfont_driver
;
635 xftfont_driver
.type
= Qxft
;
636 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
637 xftfont_driver
.list
= xftfont_list
;
638 xftfont_driver
.match
= xftfont_match
;
639 xftfont_driver
.open
= xftfont_open
;
640 xftfont_driver
.close
= xftfont_close
;
641 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
642 xftfont_driver
.done_face
= xftfont_done_face
;
643 xftfont_driver
.encode_char
= xftfont_encode_char
;
644 xftfont_driver
.text_extents
= xftfont_text_extents
;
645 xftfont_driver
.draw
= xftfont_draw
;
646 xftfont_driver
.anchor_point
= xftfont_anchor_point
;
647 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
650 xftfont_driver
.shape
= xftfont_shape
;
651 #endif /* HAVE_M17N_FLT */
652 #endif /* HAVE_LIBOTF */
654 register_font_driver (&xftfont_driver
, NULL
);
657 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
658 (do not change this comment) */