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
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
));
70 static Font xftfont_default_fid
P_ ((FRAME_PTR
));
73 /* Setup foreground and background colors of GC into FG and BG. If
74 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
78 xftfont_get_colors (f
, face
, gc
, xftface_info
, fg
, bg
)
82 struct xftface_info
*xftface_info
;
85 if (xftface_info
&& face
->gc
== gc
)
87 *fg
= xftface_info
->xft_fg
;
89 *bg
= xftface_info
->xft_bg
;
94 int fg_done
= 0, bg_done
= 0;
97 XGetGCValues (FRAME_X_DISPLAY (f
), gc
,
98 GCForeground
| GCBackground
, &xgcv
);
101 if (xgcv
.foreground
== face
->foreground
)
102 *fg
= xftface_info
->xft_fg
, fg_done
= 1;
103 else if (xgcv
.foreground
== face
->background
)
104 *fg
= xftface_info
->xft_bg
, fg_done
= 1;
107 else if (xgcv
.background
== face
->background
)
108 *bg
= xftface_info
->xft_bg
, bg_done
= 1;
109 else if (xgcv
.background
== face
->foreground
)
110 *bg
= xftface_info
->xft_fg
, bg_done
= 1;
113 if (fg_done
+ bg_done
< 2)
117 colors
[0].pixel
= fg
->pixel
= xgcv
.foreground
;
119 colors
[1].pixel
= bg
->pixel
= xgcv
.background
;
120 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
,
122 fg
->color
.alpha
= 0xFFFF;
123 fg
->color
.red
= colors
[0].red
;
124 fg
->color
.green
= colors
[0].green
;
125 fg
->color
.blue
= colors
[0].blue
;
128 bg
->color
.alpha
= 0xFFFF;
129 bg
->color
.red
= colors
[1].red
;
130 bg
->color
.green
= colors
[1].green
;
131 bg
->color
.blue
= colors
[1].blue
;
138 /* Return the default Font ID on frame F. The Returned Font ID is
139 stored in the GC of the frame F, but the font is never used. So,
140 any ID is ok as long as it is valid. */
143 xftfont_default_fid (f
)
146 static int fid_known
;
151 fid
= XLoadFont (FRAME_X_DISPLAY (f
), "fixed");
154 fid
= XLoadFont (FRAME_X_DISPLAY (f
), "*");
164 static Lisp_Object xftfont_list
P_ ((Lisp_Object
, Lisp_Object
));
165 static Lisp_Object xftfont_match
P_ ((Lisp_Object
, Lisp_Object
));
166 static struct font
*xftfont_open
P_ ((FRAME_PTR
, Lisp_Object
, int));
167 static void xftfont_close
P_ ((FRAME_PTR
, struct font
*));
168 static int xftfont_prepare_face
P_ ((FRAME_PTR
, struct face
*));
169 static void xftfont_done_face
P_ ((FRAME_PTR
, struct face
*));
170 static unsigned xftfont_encode_char
P_ ((struct font
*, int));
171 static int xftfont_text_extents
P_ ((struct font
*, unsigned *, int,
172 struct font_metrics
*));
173 static int xftfont_draw
P_ ((struct glyph_string
*, int, int, int, int, int));
175 static int xftfont_anchor_point
P_ ((struct font
*, unsigned, int,
177 static int xftfont_end_for_frame
P_ ((FRAME_PTR f
));
179 struct font_driver xftfont_driver
;
182 xftfont_list (frame
, spec
)
186 Lisp_Object val
= ftfont_driver
.list (frame
, spec
);
190 for (i
= 0; i
< ASIZE (val
); i
++)
191 ASET (AREF (val
, i
), FONT_TYPE_INDEX
, Qxft
);
196 xftfont_match (frame
, spec
)
200 Lisp_Object entity
= ftfont_driver
.match (frame
, spec
);
202 if (VECTORP (entity
))
203 ASET (entity
, FONT_TYPE_INDEX
, Qxft
);
207 extern Lisp_Object ftfont_font_format
P_ ((FcPattern
*));
209 static FcChar8 ascii_printable
[95];
212 xftfont_open (f
, entity
, pixel_size
)
217 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
218 Display
*display
= FRAME_X_DISPLAY (f
);
220 FcPattern
*pattern
, *pat
= NULL
;
222 struct xftfont_info
*xftfont_info
= NULL
;
223 XFontStruct
*xfont
= NULL
;
226 XftFont
*xftfont
= NULL
;
233 val
= AREF (entity
, FONT_EXTRA_INDEX
);
234 if (XTYPE (val
) != Lisp_Misc
235 || XMISCTYPE (val
) != Lisp_Misc_Save_Value
)
237 pattern
= XSAVE_VALUE (val
)->pointer
;
238 if (FcPatternGetString (pattern
, FC_FILE
, 0, &file
) != FcResultMatch
)
241 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
245 pat
= FcPatternCreate ();
246 FcPatternAddString (pat
, FC_FILE
, file
);
247 FcPatternAddDouble (pat
, FC_PIXEL_SIZE
, pixel_size
);
248 /*FcPatternAddBool (pat, FC_ANTIALIAS, FcTrue);*/
249 val
= AREF (entity
, FONT_FAMILY_INDEX
);
251 FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) SDATA (SYMBOL_NAME (val
)));
252 FcConfigSubstitute (NULL
, pat
, FcMatchPattern
);
255 XftDefaultSubstitute (display
, FRAME_X_SCREEN_NUMBER (f
), pat
);
256 xftfont
= XftFontOpenPattern (display
, pat
);
257 /* We should not destroy PAT here because it is kept in XFTFONT and
258 destroyed automatically when XFTFONT is closed. */
262 xftfont_info
= malloc (sizeof (struct xftfont_info
));
265 xfont
= malloc (sizeof (XFontStruct
));
268 xftfont_info
->display
= display
;
269 xftfont_info
->screen
= FRAME_X_SCREEN_NUMBER (f
);
270 xftfont_info
->xftfont
= xftfont
;
272 ft_face
= XftLockFace (xftfont
);
273 xftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
274 XftUnlockFace (xftfont
);
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 XftFontClose (xftfont_info
->display
, xftfont_info
->xftfont
);
399 free (font
->font
.name
);
401 FRAME_X_DISPLAY_INFO (f
)->n_fonts
--;
405 xftfont_prepare_face (f
, face
)
409 struct xftface_info
*xftface_info
;
412 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
413 if (face
!= face
->ascii_face
)
415 face
->extra
= face
->ascii_face
->extra
;
420 xftface_info
= malloc (sizeof (struct xftface_info
));
425 xftfont_get_colors (f
, face
, face
->gc
, NULL
,
426 &xftface_info
->xft_fg
, &xftface_info
->xft_bg
);
429 face
->extra
= xftface_info
;
434 xftfont_done_face (f
, face
)
438 struct xftface_info
*xftface_info
;
441 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
442 if (face
!= face
->ascii_face
447 xftface_info
= (struct xftface_info
*) face
->extra
;
456 xftfont_encode_char (font
, c
)
460 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
461 unsigned code
= XftCharIndex (xftfont_info
->display
, xftfont_info
->xftfont
,
464 return (code
? code
: FONT_INVALID_CODE
);
468 xftfont_text_extents (font
, code
, nglyphs
, metrics
)
472 struct font_metrics
*metrics
;
474 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
478 XftGlyphExtents (xftfont_info
->display
, xftfont_info
->xftfont
, code
, nglyphs
,
483 metrics
->lbearing
= - extents
.x
;
484 metrics
->rbearing
= - extents
.x
+ extents
.width
;
485 metrics
->width
= extents
.xOff
;
486 metrics
->ascent
= extents
.y
;
487 metrics
->descent
= extents
.height
- extents
.y
;
493 xftfont_get_xft_draw (f
)
496 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);;
501 xft_draw
= XftDrawCreate (FRAME_X_DISPLAY (f
),
504 FRAME_X_COLORMAP (f
));
508 font_put_frame_data (f
, &xftfont_driver
, xft_draw
);
514 xftfont_draw (s
, from
, to
, x
, y
, with_background
)
515 struct glyph_string
*s
;
516 int from
, to
, x
, y
, with_background
;
519 struct face
*face
= s
->face
;
520 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) s
->font_info
;
521 struct xftface_info
*xftface_info
= NULL
;
522 XftDraw
*xft_draw
= xftfont_get_xft_draw (f
);
529 if (s
->font_info
== face
->font_info
)
530 xftface_info
= (struct xftface_info
*) face
->extra
;
531 xftfont_get_colors (f
, face
, s
->gc
, xftface_info
,
532 &fg
, with_background
? &bg
: NULL
);
534 if (s
->num_clips
> 0)
535 XftDrawSetClipRectangles (xft_draw
, 0, 0, s
->clip
, s
->num_clips
);
537 XftDrawSetClip (xft_draw
, NULL
);
541 struct font
*font
= (struct font
*) face
->font_info
;
543 XftDrawRect (xft_draw
, &bg
,
544 x
, y
- face
->font
->ascent
, s
->width
, font
->font
.height
);
546 code
= alloca (sizeof (FT_UInt
) * len
);
547 for (i
= 0; i
< len
; i
++)
548 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
549 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
551 XftDrawGlyphs (xft_draw
, &fg
, xftfont_info
->xftfont
,
559 xftfont_anchor_point (font
, code
, index
, x
, y
)
565 struct xftfont_info
*xftfont_info
= (struct xftfont_info
*) font
;
566 FT_Face ft_face
= XftLockFace (xftfont_info
->xftfont
);
569 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
571 else if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
573 else if (index
>= ft_face
->glyph
->outline
.n_points
)
577 *x
= ft_face
->glyph
->outline
.points
[index
].x
;
578 *y
= ft_face
->glyph
->outline
.points
[index
].y
;
580 XftUnlockFace (xftfont_info
->xftfont
);
585 xftfont_end_for_frame (f
)
588 XftDraw
*xft_draw
= font_get_frame_data (f
, &xftfont_driver
);
593 XftDrawDestroy (xft_draw
);
595 font_put_frame_data (f
, &xftfont_driver
, NULL
);
603 xftfont_shape (lgstring
)
604 Lisp_Object lgstring
;
607 struct xftfont_info
*xftfont_info
;
611 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
612 xftfont_info
= (struct xftfont_info
*) font
;
613 if (! xftfont_info
->maybe_otf
)
615 ft_face
= XftLockFace (xftfont_info
->xftfont
);
616 if (! xftfont_info
->otf
)
618 OTF
*otf
= OTF_open_ft_face (ft_face
);
620 if (! otf
|| OTF_get_table (otf
, "head") < 0)
624 xftfont_info
->maybe_otf
= 0;
625 XftUnlockFace (xftfont_info
->xftfont
);
628 xftfont_info
->otf
= otf
;
631 result
= ftfont_shape_by_flt (lgstring
, font
, ft_face
, xftfont_info
->otf
);
632 XftUnlockFace (xftfont_info
->xftfont
);
635 #endif /* HAVE_M17N_FLT */
636 #endif /* HAVE_LIBOTF */
641 DEFSYM (Qxft
, "xft");
643 xftfont_driver
= ftfont_driver
;
644 xftfont_driver
.type
= Qxft
;
645 xftfont_driver
.get_cache
= xfont_driver
.get_cache
;
646 xftfont_driver
.list
= xftfont_list
;
647 xftfont_driver
.match
= xftfont_match
;
648 xftfont_driver
.open
= xftfont_open
;
649 xftfont_driver
.close
= xftfont_close
;
650 xftfont_driver
.prepare_face
= xftfont_prepare_face
;
651 xftfont_driver
.done_face
= xftfont_done_face
;
652 xftfont_driver
.encode_char
= xftfont_encode_char
;
653 xftfont_driver
.text_extents
= xftfont_text_extents
;
654 xftfont_driver
.draw
= xftfont_draw
;
655 xftfont_driver
.anchor_point
= xftfont_anchor_point
;
656 xftfont_driver
.end_for_frame
= xftfont_end_for_frame
;
659 xftfont_driver
.shape
= xftfont_shape
;
660 #endif /* HAVE_M17N_FLT */
661 #endif /* HAVE_LIBOTF */
663 register_font_driver (&xftfont_driver
, NULL
);
666 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
667 (do not change this comment) */