*** empty log message ***
[bpt/emacs.git] / src / xftfont.c
CommitLineData
c2f5bfd6
KH
1/* xftfont.c -- XFT font driver.
2 Copyright (C) 2006 Free Software Foundation, Inc.
4613015e 3 Copyright (C) 2006, 2007
c2f5bfd6
KH
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
6
7This file is part of GNU Emacs.
8
9GNU Emacs is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2, or (at your option)
12any later version.
13
14GNU Emacs is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with GNU Emacs; see the file COPYING. If not, write to
21the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22Boston, MA 02110-1301, USA. */
23
24#include <config.h>
25#include <stdio.h>
26#include <X11/Xlib.h>
27#include <X11/Xft/Xft.h>
28
29#include "lisp.h"
30#include "dispextern.h"
31#include "xterm.h"
32#include "frame.h"
33#include "blockinput.h"
34#include "character.h"
35#include "charset.h"
36#include "fontset.h"
37#include "font.h"
4613015e 38#include "ftfont.h"
c2f5bfd6
KH
39
40/* Xft font driver. */
41
42static Lisp_Object Qxft;
43
44/* The actual structure for Xft font that can be casted to struct
45 font. */
46
47struct xftfont_info
48{
49 struct font font;
50 Display *display;
51 int screen;
52 XftFont *xftfont;
4613015e
KH
53#ifdef HAVE_LIBOTF
54 int maybe_otf; /* Flag to tell if this may be OTF or not. */
55 OTF *otf;
794eba0f 56#endif /* HAVE_LIBOTF */
c2f5bfd6
KH
57};
58
59/* Structure pointed by (struct face *)->extra */
10aca0f7 60
c2f5bfd6
KH
61struct xftface_info
62{
10aca0f7
KH
63 XftColor xft_fg; /* color for face->foreground */
64 XftColor xft_bg; /* color for face->background */
c2f5bfd6
KH
65};
66
67static void xftfont_get_colors P_ ((FRAME_PTR, struct face *, GC gc,
68 struct xftface_info *,
69 XftColor *fg, XftColor *bg));
70static Font xftfont_default_fid P_ ((FRAME_PTR));
71
72
10aca0f7
KH
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
75 may be NULL. */
76
c2f5bfd6
KH
77static void
78xftfont_get_colors (f, face, gc, xftface_info, fg, bg)
79 FRAME_PTR f;
80 struct face *face;
81 GC gc;
82 struct xftface_info *xftface_info;
83 XftColor *fg, *bg;
84{
85 if (xftface_info && face->gc == gc)
86 {
87 *fg = xftface_info->xft_fg;
88 if (bg)
89 *bg = xftface_info->xft_bg;
90 }
91 else
92 {
93 XGCValues xgcv;
94 int fg_done = 0, bg_done = 0;
95
96 BLOCK_INPUT;
97 XGetGCValues (FRAME_X_DISPLAY (f), gc,
98 GCForeground | GCBackground, &xgcv);
99 if (xftface_info)
100 {
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;
105 if (! bg)
106 bg_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;
111 }
112
113 if (fg_done + bg_done < 2)
114 {
115 XColor colors[2];
116
117 colors[0].pixel = fg->pixel = xgcv.foreground;
118 if (bg)
119 colors[1].pixel = bg->pixel = xgcv.background;
120 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors,
121 bg ? 2 : 1);
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;
126 if (bg)
127 {
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;
132 }
133 }
134 UNBLOCK_INPUT;
135 }
136}
137
10aca0f7
KH
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. */
c2f5bfd6
KH
141
142static Font
143xftfont_default_fid (f)
144 FRAME_PTR f;
145{
146 static int fid_known;
147 static Font fid;
148
149 if (! fid_known)
150 {
151 fid = XLoadFont (FRAME_X_DISPLAY (f), "fixed");
152 if (! fid)
153 {
154 fid = XLoadFont (FRAME_X_DISPLAY (f), "*");
155 if (! fid)
156 abort ();
157 }
322f8671 158 fid_known = 1;
c2f5bfd6
KH
159 }
160 return fid;
161}
162
163
164static Lisp_Object xftfont_list P_ ((Lisp_Object, Lisp_Object));
10aca0f7 165static Lisp_Object xftfont_match P_ ((Lisp_Object, Lisp_Object));
c2f5bfd6
KH
166static struct font *xftfont_open P_ ((FRAME_PTR, Lisp_Object, int));
167static void xftfont_close P_ ((FRAME_PTR, struct font *));
168static int xftfont_prepare_face P_ ((FRAME_PTR, struct face *));
169static void xftfont_done_face P_ ((FRAME_PTR, struct face *));
170static unsigned xftfont_encode_char P_ ((struct font *, int));
171static int xftfont_text_extents P_ ((struct font *, unsigned *, int,
172 struct font_metrics *));
173static int xftfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
174
175static int xftfont_anchor_point P_ ((struct font *, unsigned, int,
176 int *, int *));
a92ee6bf 177static int xftfont_end_for_frame P_ ((FRAME_PTR f));
c2f5bfd6
KH
178
179struct font_driver xftfont_driver;
180
181static Lisp_Object
182xftfont_list (frame, spec)
183 Lisp_Object frame;
184 Lisp_Object spec;
185{
186 Lisp_Object val = ftfont_driver.list (frame, spec);
10aca0f7 187 int i;
c2f5bfd6
KH
188
189 if (! NILP (val))
10aca0f7
KH
190 for (i = 0; i < ASIZE (val); i++)
191 ASET (AREF (val, i), FONT_TYPE_INDEX, Qxft);
c2f5bfd6
KH
192 return val;
193}
194
10aca0f7
KH
195static Lisp_Object
196xftfont_match (frame, spec)
197 Lisp_Object frame;
198 Lisp_Object spec;
199{
200 Lisp_Object entity = ftfont_driver.match (frame, spec);
201
202 if (VECTORP (entity))
203 ASET (entity, FONT_TYPE_INDEX, Qxft);
204 return entity;
205}
206
98d12656
KH
207extern Lisp_Object ftfont_font_format P_ ((FcPattern *));
208
c2f5bfd6
KH
209static FcChar8 ascii_printable[95];
210
211static struct font *
212xftfont_open (f, entity, pixel_size)
213 FRAME_PTR f;
214 Lisp_Object entity;
215 int pixel_size;
216{
217 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
218 Display *display = FRAME_X_DISPLAY (f);
219 Lisp_Object val;
2d93c6bd
KH
220 FcPattern *pattern, *pat = NULL;
221 FcChar8 *file;
222 struct xftfont_info *xftfont_info = NULL;
223 XFontStruct *xfont = NULL;
c2f5bfd6
KH
224 struct font *font;
225 double size = 0;
2d93c6bd 226 XftFont *xftfont = NULL;
c2f5bfd6 227 int spacing;
2d93c6bd 228 char *name;
dcce3c58 229 int len;
91c5bb27 230 XGlyphInfo extents;
365131ac 231 FT_Face ft_face;
c2f5bfd6
KH
232
233 val = AREF (entity, FONT_EXTRA_INDEX);
234 if (XTYPE (val) != Lisp_Misc
235 || XMISCTYPE (val) != Lisp_Misc_Save_Value)
236 return NULL;
237 pattern = XSAVE_VALUE (val)->pointer;
238 if (FcPatternGetString (pattern, FC_FILE, 0, &file) != FcResultMatch)
239 return NULL;
240
241 size = XINT (AREF (entity, FONT_SIZE_INDEX));
242 if (size == 0)
243 size = pixel_size;
dcce3c58 244
c2f5bfd6
KH
245 pat = FcPatternCreate ();
246 FcPatternAddString (pat, FC_FILE, file);
247 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
fa762662 248 /*FcPatternAddBool (pat, FC_ANTIALIAS, FcTrue);*/
3cc2aca0
KH
249 val = AREF (entity, FONT_FAMILY_INDEX);
250 if (! NILP (val))
251 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
252 FcConfigSubstitute (NULL, pat, FcMatchPattern);
dcce3c58
KH
253
254 BLOCK_INPUT;
4f4426f9 255 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
c2f5bfd6
KH
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. */
259 if (! xftfont)
2d93c6bd 260 goto err;
c2f5bfd6
KH
261
262 xftfont_info = malloc (sizeof (struct xftfont_info));
263 if (! xftfont_info)
2d93c6bd 264 goto err;
c2f5bfd6 265 xfont = malloc (sizeof (XFontStruct));
2d93c6bd
KH
266 if (! xfont)
267 goto err;
c2f5bfd6
KH
268 xftfont_info->display = display;
269 xftfont_info->screen = FRAME_X_SCREEN_NUMBER (f);
270 xftfont_info->xftfont = xftfont;
4613015e 271#ifdef HAVE_LIBOTF
365131ac
KH
272 ft_face = XftLockFace (xftfont);
273 xftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
274 XftUnlockFace (xftfont);
4613015e 275 xftfont_info->otf = NULL;
794eba0f 276#endif /* HAVE_LIBOTF */
c2f5bfd6
KH
277
278 font = (struct font *) xftfont_info;
b2e0f618 279 font->format = ftfont_font_format (xftfont->pattern);
c2f5bfd6
KH
280 font->entity = entity;
281 font->pixel_size = size;
282 font->driver = &xftfont_driver;
560fd3fa 283 len = 96;
2d93c6bd
KH
284 name = malloc (len);
285 while (name && font_unparse_fcname (entity, pixel_size, name, len) < 0)
286 {
287 char *new = realloc (name, len += 32);
288
289 if (! new)
290 free (name);
291 name = new;
292 }
293 if (! name)
294 goto err;
295 font->font.full_name = font->font.name = name;
c2f5bfd6
KH
296 font->file_name = (char *) file;
297 font->font.size = xftfont->max_advance_width;
8bf90572 298 font->font.charset = font->encoding_charset = font->repertory_charset = -1;
c2f5bfd6
KH
299
300 if (FcPatternGetInteger (xftfont->pattern, FC_SPACING, 0, &spacing)
301 != FcResultMatch)
302 spacing = FC_PROPORTIONAL;
91c5bb27
KH
303 if (! ascii_printable[0])
304 {
305 int i;
306 for (i = 0; i < 95; i++)
307 ascii_printable[i] = ' ' + i;
308 }
c2f5bfd6 309 if (spacing != FC_PROPORTIONAL)
91c5bb27
KH
310 {
311 font->font.average_width = font->font.space_width
312 = xftfont->max_advance_width;
313 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
314 }
c2f5bfd6
KH
315 else
316 {
c2f5bfd6
KH
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;
324 }
dcce3c58 325 UNBLOCK_INPUT;
c2f5bfd6 326
91c5bb27
KH
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;
334
c2f5bfd6
KH
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;
338
339 font->font.baseline_offset = 0;
340 font->font.relative_compose = 0;
341 font->font.default_ascent = 0;
342 font->font.vertical_centering = 0;
343
344 /* Setup pseudo XFontStruct */
345 xfont->fid = xftfont_default_fid (f);
91c5bb27
KH
346 xfont->ascent = font->ascent;
347 xfont->descent = font->descent;
348 xfont->max_bounds.descent = font->descent;
c2f5bfd6
KH
349 xfont->max_bounds.width = xftfont->max_advance_width;
350 xfont->min_bounds.width = font->font.space_width;
351 font->font.font = xfont;
352
353 dpyinfo->n_fonts++;
354
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)
361 {
362 dpyinfo->smallest_font_height = font->font.height;
363 dpyinfo->smallest_char_width = font->min_width;
364 fonts_changed_p = 1;
365 }
366 else
367 {
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;
374 }
375
376 return font;
2d93c6bd
KH
377
378 err:
379 if (xftfont) XftFontClose (display, xftfont);
380 UNBLOCK_INPUT;
381 if (xftfont_info) free (xftfont_info);
382 if (xfont) free (xfont);
383 return NULL;
c2f5bfd6
KH
384}
385
386static void
387xftfont_close (f, font)
388 FRAME_PTR f;
389 struct font *font;
390{
391 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
392
4613015e
KH
393#ifdef HAVE_LIBOTF
394 if (xftfont_info->otf)
395 OTF_close (xftfont_info->otf);
396#endif
c2f5bfd6 397 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
dcce3c58
KH
398 if (font->font.name)
399 free (font->font.name);
c2f5bfd6
KH
400 free (font);
401 FRAME_X_DISPLAY_INFO (f)->n_fonts--;
402}
403
c2f5bfd6
KH
404static int
405xftfont_prepare_face (f, face)
406 FRAME_PTR f;
407 struct face *face;
408{
e2d0c925 409 struct xftface_info *xftface_info;
c2f5bfd6 410
a703d27d
KH
411#if 0
412 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
e2d0c925
KH
413 if (face != face->ascii_face)
414 {
415 face->extra = face->ascii_face->extra;
416 return 0;
417 }
a703d27d 418#endif
e2d0c925
KH
419
420 xftface_info = malloc (sizeof (struct xftface_info));
c2f5bfd6
KH
421 if (! xftface_info)
422 return -1;
423
424 BLOCK_INPUT;
c2f5bfd6
KH
425 xftfont_get_colors (f, face, face->gc, NULL,
426 &xftface_info->xft_fg, &xftface_info->xft_bg);
427 UNBLOCK_INPUT;
428
429 face->extra = xftface_info;
430 return 0;
431}
432
433static void
434xftfont_done_face (f, face)
435 FRAME_PTR f;
436 struct face *face;
437{
e2d0c925
KH
438 struct xftface_info *xftface_info;
439
a703d27d
KH
440#if 0
441 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
e2d0c925
KH
442 if (face != face->ascii_face
443 || ! face->extra)
444 return;
a703d27d 445#endif
c2f5bfd6 446
e2d0c925 447 xftface_info = (struct xftface_info *) face->extra;
773039e8
JD
448 if (xftface_info)
449 {
773039e8 450 free (xftface_info);
a92ee6bf 451 face->extra = NULL;
773039e8 452 }
c2f5bfd6
KH
453}
454
455static unsigned
456xftfont_encode_char (font, c)
457 struct font *font;
458 int c;
459{
460 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
461 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
462 (FcChar32) c);
463
464 return (code ? code : 0xFFFFFFFF);
465}
466
467static int
468xftfont_text_extents (font, code, nglyphs, metrics)
469 struct font *font;
470 unsigned *code;
471 int nglyphs;
472 struct font_metrics *metrics;
473{
474 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
475 XGlyphInfo extents;
476
477 BLOCK_INPUT;
478 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
479 &extents);
480 UNBLOCK_INPUT;
481 if (metrics)
482 {
483 metrics->lbearing = - extents.x;
484 metrics->rbearing = - extents.x + extents.width;
485 metrics->width = extents.xOff;
486 metrics->ascent = extents.y;
4b848612 487 metrics->descent = extents.height - extents.y;
c2f5bfd6
KH
488 }
489 return extents.xOff;
490}
491
a92ee6bf
KH
492static XftDraw *
493xftfont_get_xft_draw (f)
494 FRAME_PTR f;
495{
496 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);;
497
498 if (! xft_draw)
499 {
500 BLOCK_INPUT;
501 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
502 FRAME_X_WINDOW (f),
503 FRAME_X_VISUAL (f),
504 FRAME_X_COLORMAP (f));
505 UNBLOCK_INPUT;
506 if (! xft_draw)
507 abort ();
508 font_put_frame_data (f, &xftfont_driver, xft_draw);
509 }
510 return xft_draw;
511}
512
c2f5bfd6
KH
513static int
514xftfont_draw (s, from, to, x, y, with_background)
515 struct glyph_string *s;
516 int from, to, x, y, with_background;
517{
518 FRAME_PTR f = s->f;
519 struct face *face = s->face;
c78c1659
KH
520 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font_info;
521 struct xftface_info *xftface_info = NULL;
a92ee6bf 522 XftDraw *xft_draw = xftfont_get_xft_draw (f);
c2f5bfd6
KH
523 FT_UInt *code;
524 XftColor fg, bg;
525 XRectangle r;
526 int len = to - from;
527 int i;
528
c78c1659 529 if (s->font_info == face->font_info)
a92ee6bf 530 xftface_info = (struct xftface_info *) face->extra;
c2f5bfd6 531 xftfont_get_colors (f, face, s->gc, xftface_info,
322f8671 532 &fg, with_background ? &bg : NULL);
c2f5bfd6 533 BLOCK_INPUT;
03d198e8
KH
534 if (s->num_clips > 0)
535 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
536 else
537 XftDrawSetClip (xft_draw, NULL);
538
c2f5bfd6
KH
539 if (with_background)
540 {
541 struct font *font = (struct font *) face->font_info;
542
c78c1659 543 XftDrawRect (xft_draw, &bg,
c2f5bfd6
KH
544 x, y - face->font->ascent, s->width, font->font.height);
545 }
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));
550
c78c1659 551 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
c2f5bfd6 552 x, y, code, len);
c2f5bfd6
KH
553 UNBLOCK_INPUT;
554
555 return len;
556}
557
558static int
559xftfont_anchor_point (font, code, index, x, y)
560 struct font *font;
561 unsigned code;
562 int index;
563 int *x, *y;
564{
565 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
365131ac
KH
566 FT_Face ft_face = XftLockFace (xftfont_info->xftfont);
567 int result;
c2f5bfd6
KH
568
569 if (FT_Load_Glyph (ft_face, code, FT_LOAD_DEFAULT) != 0)
365131ac
KH
570 result = -1;
571 else if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
572 result = -1;
573 else if (index >= ft_face->glyph->outline.n_points)
574 result = -1;
575 else
576 {
577 *x = ft_face->glyph->outline.points[index].x;
578 *y = ft_face->glyph->outline.points[index].y;
579 }
580 XftUnlockFace (xftfont_info->xftfont);
581 return result;
c2f5bfd6
KH
582}
583
a92ee6bf
KH
584static int
585xftfont_end_for_frame (f)
586 FRAME_PTR f;
587{
588 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
589
590 if (xft_draw)
591 {
592 BLOCK_INPUT;
593 XftDrawDestroy (xft_draw);
594 UNBLOCK_INPUT;
595 font_put_frame_data (f, &xftfont_driver, NULL);
596 }
597 return 0;
598}
c2f5bfd6 599
4613015e
KH
600#ifdef HAVE_LIBOTF
601#ifdef HAVE_M17N_FLT
602static Lisp_Object
603xftfont_shape (lgstring)
604 Lisp_Object lgstring;
605{
606 struct font *font;
607 struct xftfont_info *xftfont_info;
365131ac
KH
608 int result;
609 FT_Face ft_face;
4613015e
KH
610
611 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
612 xftfont_info = (struct xftfont_info *) font;
613 if (! xftfont_info->maybe_otf)
614 return Qnil;
365131ac 615 ft_face = XftLockFace (xftfont_info->xftfont);
4613015e
KH
616 if (! xftfont_info->otf)
617 {
365131ac 618 OTF *otf = OTF_open_ft_face (ft_face);
4613015e
KH
619
620 if (! otf || OTF_get_table (otf, "head") < 0)
621 {
622 if (otf)
623 OTF_close (otf);
624 xftfont_info->maybe_otf = 0;
365131ac 625 XftUnlockFace (xftfont_info->xftfont);
4613015e
KH
626 return 0;
627 }
628 xftfont_info->otf = otf;
629 }
630
365131ac
KH
631 result = ftfont_shape_by_flt (lgstring, font, ft_face, xftfont_info->otf);
632 XftUnlockFace (xftfont_info->xftfont);
633 return result;
4613015e
KH
634}
635#endif /* HAVE_M17N_FLT */
636#endif /* HAVE_LIBOTF */
637
c2f5bfd6
KH
638void
639syms_of_xftfont ()
640{
641 DEFSYM (Qxft, "xft");
642
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;
10aca0f7 647 xftfont_driver.match = xftfont_match;
c2f5bfd6
KH
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;
a92ee6bf 656 xftfont_driver.end_for_frame = xftfont_end_for_frame;
4613015e
KH
657#ifdef HAVE_LIBOTF
658#ifdef HAVE_M17N_FLT
659 xftfont_driver.shape = xftfont_shape;
660#endif /* HAVE_M17N_FLT */
661#endif /* HAVE_LIBOTF */
c2f5bfd6
KH
662
663 register_font_driver (&xftfont_driver, NULL);
664}
885b7d09
MB
665
666/* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
667 (do not change this comment) */