(xftfont_open): Add FOUNDRY, SPACING, DPI, SCALABLE to the pattern.
[bpt/emacs.git] / src / xftfont.c
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
6
7 This file is part of GNU Emacs.
8
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 of the License, or
12 (at your option) any later version.
13
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.
18
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <X11/Xlib.h>
25 #include <X11/Xft/Xft.h>
26
27 #include "lisp.h"
28 #include "dispextern.h"
29 #include "xterm.h"
30 #include "frame.h"
31 #include "blockinput.h"
32 #include "character.h"
33 #include "charset.h"
34 #include "fontset.h"
35 #include "font.h"
36 #include "ftfont.h"
37
38 /* Xft font driver. */
39
40 static Lisp_Object Qxft;
41 static Lisp_Object QChinting , QCautohint, QChintstyle, QCrgba, QCembolden;
42
43 /* The actual structure for Xft font that can be casted to struct
44 font. */
45
46 struct xftfont_info
47 {
48 struct font font;
49 Display *display;
50 int screen;
51 XftFont *xftfont;
52 #ifdef HAVE_LIBOTF
53 int maybe_otf; /* Flag to tell if this may be OTF or not. */
54 OTF *otf;
55 #endif /* HAVE_LIBOTF */
56 };
57
58 /* Structure pointed by (struct face *)->extra */
59
60 struct xftface_info
61 {
62 XftColor xft_fg; /* color for face->foreground */
63 XftColor xft_bg; /* color for face->background */
64 };
65
66 static void xftfont_get_colors P_ ((FRAME_PTR, struct face *, GC gc,
67 struct xftface_info *,
68 XftColor *fg, XftColor *bg));
69
70
71 /* Setup foreground and background colors of GC into FG and BG. If
72 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
73 may be NULL. */
74
75 static void
76 xftfont_get_colors (f, face, gc, xftface_info, fg, bg)
77 FRAME_PTR f;
78 struct face *face;
79 GC gc;
80 struct xftface_info *xftface_info;
81 XftColor *fg, *bg;
82 {
83 if (xftface_info && face->gc == gc)
84 {
85 *fg = xftface_info->xft_fg;
86 if (bg)
87 *bg = xftface_info->xft_bg;
88 }
89 else
90 {
91 XGCValues xgcv;
92 int fg_done = 0, bg_done = 0;
93
94 BLOCK_INPUT;
95 XGetGCValues (FRAME_X_DISPLAY (f), gc,
96 GCForeground | GCBackground, &xgcv);
97 if (xftface_info)
98 {
99 if (xgcv.foreground == face->foreground)
100 *fg = xftface_info->xft_fg, fg_done = 1;
101 else if (xgcv.foreground == face->background)
102 *fg = xftface_info->xft_bg, fg_done = 1;
103 if (! bg)
104 bg_done = 1;
105 else if (xgcv.background == face->background)
106 *bg = xftface_info->xft_bg, bg_done = 1;
107 else if (xgcv.background == face->foreground)
108 *bg = xftface_info->xft_fg, bg_done = 1;
109 }
110
111 if (fg_done + bg_done < 2)
112 {
113 XColor colors[2];
114
115 colors[0].pixel = fg->pixel = xgcv.foreground;
116 if (bg)
117 colors[1].pixel = bg->pixel = xgcv.background;
118 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors,
119 bg ? 2 : 1);
120 fg->color.alpha = 0xFFFF;
121 fg->color.red = colors[0].red;
122 fg->color.green = colors[0].green;
123 fg->color.blue = colors[0].blue;
124 if (bg)
125 {
126 bg->color.alpha = 0xFFFF;
127 bg->color.red = colors[1].red;
128 bg->color.green = colors[1].green;
129 bg->color.blue = colors[1].blue;
130 }
131 }
132 UNBLOCK_INPUT;
133 }
134 }
135
136
137 static Lisp_Object xftfont_list P_ ((Lisp_Object, Lisp_Object));
138 static Lisp_Object xftfont_match P_ ((Lisp_Object, Lisp_Object));
139 static Lisp_Object xftfont_open P_ ((FRAME_PTR, Lisp_Object, int));
140 static void xftfont_close P_ ((FRAME_PTR, struct font *));
141 static int xftfont_prepare_face P_ ((FRAME_PTR, struct face *));
142 static void xftfont_done_face P_ ((FRAME_PTR, struct face *));
143 static unsigned xftfont_encode_char P_ ((struct font *, int));
144 static int xftfont_text_extents P_ ((struct font *, unsigned *, int,
145 struct font_metrics *));
146 static int xftfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
147
148 static int xftfont_anchor_point P_ ((struct font *, unsigned, int,
149 int *, int *));
150 static int xftfont_end_for_frame P_ ((FRAME_PTR f));
151
152 struct font_driver xftfont_driver;
153
154 static Lisp_Object
155 xftfont_list (frame, spec)
156 Lisp_Object frame;
157 Lisp_Object spec;
158 {
159 Lisp_Object list = ftfont_driver.list (frame, spec), tail;
160
161 for (tail = list; CONSP (tail); tail = XCDR (tail))
162 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
163 return list;
164 }
165
166 static Lisp_Object
167 xftfont_match (frame, spec)
168 Lisp_Object frame;
169 Lisp_Object spec;
170 {
171 Lisp_Object entity = ftfont_driver.match (frame, spec);
172
173 if (! NILP (entity))
174 ASET (entity, FONT_TYPE_INDEX, Qxft);
175 return entity;
176 }
177
178 extern Lisp_Object ftfont_font_format P_ ((FcPattern *));
179 extern Lisp_Object QCantialias;
180
181 static FcChar8 ascii_printable[95];
182
183 static Lisp_Object
184 xftfont_open (f, entity, pixel_size)
185 FRAME_PTR f;
186 Lisp_Object entity;
187 int pixel_size;
188 {
189 FcResult result;
190 Display *display = FRAME_X_DISPLAY (f);
191 Lisp_Object val, filename, tail, font_object;
192 FcPattern *pat = NULL, *match;
193 struct xftfont_info *xftfont_info = NULL;
194 struct font *font;
195 double size = 0;
196 XftFont *xftfont = NULL;
197 int spacing;
198 char name[256];
199 int len, i;
200 XGlyphInfo extents;
201 FT_Face ft_face;
202
203 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
204 if (! CONSP (val))
205 return Qnil;
206 val = XCDR (val);
207 filename = XCAR (val);
208 size = XINT (AREF (entity, FONT_SIZE_INDEX));
209 if (size == 0)
210 size = pixel_size;
211 pat = FcPatternCreate ();
212 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
213 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
214 i = FONT_SLANT_NUMERIC (entity) - 100;
215 if (i < 0) i = 0;
216 FcPatternAddInteger (pat, FC_SLANT, i);
217 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
218 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
219 val = AREF (entity, FONT_FAMILY_INDEX);
220 if (! NILP (val))
221 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
222 val = AREF (entity, FONT_FOUNDRY_INDEX);
223 if (! NILP (val))
224 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
225 val = AREF (entity, FONT_SPACING_INDEX);
226 if (! NILP (val))
227 FcPatternAddInteger (pat, FC_SPACING, XINT (val));
228 val = AREF (entity, FONT_DPI_INDEX);
229 if (! NILP (val))
230 {
231 double dbl = XINT (val);
232
233 FcPatternAddDouble (pat, FC_DPI, dbl);
234 }
235 val = AREF (entity, FONT_AVGWIDTH_INDEX);
236 if (INTEGERP (val) && XINT (val) == 0)
237 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
238
239 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
240 {
241 Lisp_Object key, val;
242
243 key = XCAR (XCAR (tail)), val = XCDR (XCAR (tail));
244 if (EQ (key, QCantialias))
245 FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
246 else if (EQ (key, QChinting))
247 FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
248 else if (EQ (key, QCautohint))
249 FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
250 else if (EQ (key, QChintstyle))
251 {
252 if (INTEGERP (val))
253 FcPatternAddInteger (pat, FC_RGBA, XINT (val));
254 }
255 else if (EQ (key, QCrgba))
256 {
257 if (INTEGERP (val))
258 FcPatternAddInteger (pat, FC_RGBA, XINT (val));
259 }
260 else if (EQ (key, QCembolden))
261 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
262 }
263 FcConfigSubstitute (NULL, pat, FcMatchPattern);
264
265 BLOCK_INPUT;
266 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
267 match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
268 FcPatternDestroy (pat);
269 xftfont = XftFontOpenPattern (display, match);
270 UNBLOCK_INPUT;
271
272 if (! xftfont)
273 return Qnil;
274 /* We should not destroy PAT here because it is kept in XFTFONT and
275 destroyed automatically when XFTFONT is closed. */
276 font_object = font_make_object (VECSIZE (struct xftfont_info));
277 ASET (font_object, FONT_TYPE_INDEX, Qxft);
278 for (i = 1; i < FONT_ENTITY_MAX; i++)
279 ASET (font_object, i, AREF (entity, i));
280 ASET (font_object, FONT_SIZE_INDEX, make_number (size));
281 len = font_unparse_xlfd (entity, size, name, 256);
282 if (len > 0)
283 ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len));
284 len = font_unparse_fcname (entity, size, name, 256);
285 if (len > 0)
286 ASET (font_object, FONT_FULLNAME_INDEX, make_unibyte_string (name, len));
287 else
288 ASET (font_object, FONT_FULLNAME_INDEX,
289 AREF (font_object, FONT_NAME_INDEX));
290 ASET (font_object, FONT_FILE_INDEX, filename);
291 ASET (font_object, FONT_FORMAT_INDEX,
292 ftfont_font_format (xftfont->pattern));
293 font = XFONT_OBJECT (font_object);
294 font->pixel_size = pixel_size;
295 font->driver = &xftfont_driver;
296 font->encoding_charset = font->repertory_charset = -1;
297
298 xftfont_info = (struct xftfont_info *) font;
299 xftfont_info->display = display;
300 xftfont_info->screen = FRAME_X_SCREEN_NUMBER (f);
301 xftfont_info->xftfont = xftfont;
302 font->pixel_size = size;
303 font->driver = &xftfont_driver;
304 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
305 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
306 else
307 spacing = FC_PROPORTIONAL;
308 if (! ascii_printable[0])
309 {
310 int i;
311 for (i = 0; i < 95; i++)
312 ascii_printable[i] = ' ' + i;
313 }
314 BLOCK_INPUT;
315 if (spacing != FC_PROPORTIONAL)
316 {
317 font->min_width = font->average_width = font->space_width
318 = xftfont->max_advance_width;
319 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
320 }
321 else
322 {
323 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
324 font->space_width = extents.xOff;
325 if (font->space_width <= 0)
326 /* dirty workaround */
327 font->space_width = pixel_size;
328 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
329 font->average_width = (font->space_width + extents.xOff) / 95;
330 }
331 UNBLOCK_INPUT;
332
333 font->ascent = xftfont->ascent;
334 font->descent = xftfont->descent;
335 if (pixel_size >= 5)
336 {
337 /* The above condition is a dirty workaround because
338 XftTextExtents8 behaves strangely for some fonts
339 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
340 if (font->ascent < extents.y)
341 font->ascent = extents.y;
342 if (font->descent < extents.height - extents.y)
343 font->descent = extents.height - extents.y;
344 }
345 font->height = font->ascent + font->descent;
346
347 ft_face = XftLockFace (xftfont);
348 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
349 {
350 int upEM = ft_face->units_per_EM;
351
352 font->underline_position = -ft_face->underline_position * size / upEM;
353 font->underline_thickness = -ft_face->underline_thickness * size / upEM;
354 if (font->underline_thickness > 2)
355 font->underline_position -= font->underline_thickness / 2;
356 }
357 else
358 {
359 font->underline_position = -1;
360 font->underline_thickness = 0;
361 }
362 #ifdef HAVE_LIBOTF
363 xftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
364 xftfont_info->otf = NULL;
365 #endif /* HAVE_LIBOTF */
366 XftUnlockFace (xftfont);
367
368 /* Unfortunately Xft doesn't provide a way to get minimum char
369 width. So, we use space_width instead. */
370 font->min_width = font->space_width;
371
372 font->baseline_offset = 0;
373 font->relative_compose = 0;
374 font->default_ascent = 0;
375 font->vertical_centering = 0;
376
377 return font_object;
378 }
379
380 static void
381 xftfont_close (f, font)
382 FRAME_PTR f;
383 struct font *font;
384 {
385 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
386
387 #ifdef HAVE_LIBOTF
388 if (xftfont_info->otf)
389 OTF_close (xftfont_info->otf);
390 #endif
391 BLOCK_INPUT;
392 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
393 UNBLOCK_INPUT;
394 }
395
396 static int
397 xftfont_prepare_face (f, face)
398 FRAME_PTR f;
399 struct face *face;
400 {
401 struct xftface_info *xftface_info;
402
403 #if 0
404 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
405 if (face != face->ascii_face)
406 {
407 face->extra = face->ascii_face->extra;
408 return 0;
409 }
410 #endif
411
412 xftface_info = malloc (sizeof (struct xftface_info));
413 if (! xftface_info)
414 return -1;
415 xftfont_get_colors (f, face, face->gc, NULL,
416 &xftface_info->xft_fg, &xftface_info->xft_bg);
417 face->extra = xftface_info;
418 return 0;
419 }
420
421 static void
422 xftfont_done_face (f, face)
423 FRAME_PTR f;
424 struct face *face;
425 {
426 struct xftface_info *xftface_info;
427
428 #if 0
429 /* This doesn't work if face->ascii_face doesn't use an Xft font. */
430 if (face != face->ascii_face
431 || ! face->extra)
432 return;
433 #endif
434
435 xftface_info = (struct xftface_info *) face->extra;
436 if (xftface_info)
437 {
438 free (xftface_info);
439 face->extra = NULL;
440 }
441 }
442
443 static unsigned
444 xftfont_encode_char (font, c)
445 struct font *font;
446 int c;
447 {
448 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
449 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
450 (FcChar32) c);
451
452 return (code ? code : FONT_INVALID_CODE);
453 }
454
455 static int
456 xftfont_text_extents (font, code, nglyphs, metrics)
457 struct font *font;
458 unsigned *code;
459 int nglyphs;
460 struct font_metrics *metrics;
461 {
462 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
463 XGlyphInfo extents;
464
465 BLOCK_INPUT;
466 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
467 &extents);
468 UNBLOCK_INPUT;
469 if (metrics)
470 {
471 metrics->lbearing = - extents.x;
472 metrics->rbearing = - extents.x + extents.width;
473 metrics->width = extents.xOff;
474 metrics->ascent = extents.y;
475 metrics->descent = extents.height - extents.y;
476 }
477 return extents.xOff;
478 }
479
480 static XftDraw *
481 xftfont_get_xft_draw (f)
482 FRAME_PTR f;
483 {
484 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);;
485
486 if (! xft_draw)
487 {
488 BLOCK_INPUT;
489 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
490 FRAME_X_WINDOW (f),
491 FRAME_X_VISUAL (f),
492 FRAME_X_COLORMAP (f));
493 UNBLOCK_INPUT;
494 if (! xft_draw)
495 abort ();
496 font_put_frame_data (f, &xftfont_driver, xft_draw);
497 }
498 return xft_draw;
499 }
500
501 static int
502 xftfont_draw (s, from, to, x, y, with_background)
503 struct glyph_string *s;
504 int from, to, x, y, with_background;
505 {
506 FRAME_PTR f = s->f;
507 struct face *face = s->face;
508 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
509 struct xftface_info *xftface_info = NULL;
510 XftDraw *xft_draw = xftfont_get_xft_draw (f);
511 FT_UInt *code;
512 XftColor fg, bg;
513 int len = to - from;
514 int i;
515
516 if (s->font == face->font)
517 xftface_info = (struct xftface_info *) face->extra;
518 xftfont_get_colors (f, face, s->gc, xftface_info,
519 &fg, with_background ? &bg : NULL);
520 BLOCK_INPUT;
521 if (s->num_clips > 0)
522 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
523 else
524 XftDrawSetClip (xft_draw, NULL);
525
526 if (with_background)
527 XftDrawRect (xft_draw, &bg,
528 x, y - face->font->ascent, s->width, face->font->height);
529 code = alloca (sizeof (FT_UInt) * len);
530 for (i = 0; i < len; i++)
531 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
532 | XCHAR2B_BYTE2 (s->char2b + from + i));
533
534 if (s->padding_p)
535 for (i = 0; i < len; i++)
536 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
537 x + i, y, code + i, 1);
538 else
539 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
540 x, y, code, len);
541 UNBLOCK_INPUT;
542
543 return len;
544 }
545
546 static int
547 xftfont_anchor_point (font, code, index, x, y)
548 struct font *font;
549 unsigned code;
550 int index;
551 int *x, *y;
552 {
553 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
554 FT_Face ft_face = XftLockFace (xftfont_info->xftfont);
555 int result;
556
557 if (FT_Load_Glyph (ft_face, code, FT_LOAD_DEFAULT) != 0)
558 result = -1;
559 else if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
560 result = -1;
561 else if (index >= ft_face->glyph->outline.n_points)
562 result = -1;
563 else
564 {
565 *x = ft_face->glyph->outline.points[index].x;
566 *y = ft_face->glyph->outline.points[index].y;
567 }
568 XftUnlockFace (xftfont_info->xftfont);
569 return result;
570 }
571
572 static int
573 xftfont_end_for_frame (f)
574 FRAME_PTR f;
575 {
576 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
577
578 if (xft_draw)
579 {
580 BLOCK_INPUT;
581 XftDrawDestroy (xft_draw);
582 UNBLOCK_INPUT;
583 font_put_frame_data (f, &xftfont_driver, NULL);
584 }
585 return 0;
586 }
587
588 #ifdef HAVE_LIBOTF
589 #ifdef HAVE_M17N_FLT
590 static Lisp_Object
591 xftfont_shape (lgstring)
592 Lisp_Object lgstring;
593 {
594 struct font *font;
595 struct xftfont_info *xftfont_info;
596 Lisp_Object result;
597 FT_Face ft_face;
598
599 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
600 xftfont_info = (struct xftfont_info *) font;
601 if (! xftfont_info->maybe_otf)
602 return Qnil;
603 ft_face = XftLockFace (xftfont_info->xftfont);
604 if (! xftfont_info->otf)
605 {
606 OTF *otf = OTF_open_ft_face (ft_face);
607
608 if (! otf || OTF_get_table (otf, "head") < 0)
609 {
610 if (otf)
611 OTF_close (otf);
612 xftfont_info->maybe_otf = 0;
613 XftUnlockFace (xftfont_info->xftfont);
614 return Qnil;
615 }
616 xftfont_info->otf = otf;
617 }
618
619 result = ftfont_shape_by_flt (lgstring, font, ft_face, xftfont_info->otf);
620 XftUnlockFace (xftfont_info->xftfont);
621 return result;
622 }
623 #endif /* HAVE_M17N_FLT */
624 #endif /* HAVE_LIBOTF */
625
626 void
627 syms_of_xftfont ()
628 {
629 DEFSYM (Qxft, "xft");
630 DEFSYM (QChinting, ":hinting");
631 DEFSYM (QCautohint, ":autohing");
632 DEFSYM (QChintstyle, ":hintstyle");
633 DEFSYM (QCrgba, ":rgba");
634 DEFSYM (QCembolden, ":embolden");
635
636 xftfont_driver = ftfont_driver;
637 xftfont_driver.type = Qxft;
638 xftfont_driver.get_cache = xfont_driver.get_cache;
639 xftfont_driver.list = xftfont_list;
640 xftfont_driver.match = xftfont_match;
641 xftfont_driver.open = xftfont_open;
642 xftfont_driver.close = xftfont_close;
643 xftfont_driver.prepare_face = xftfont_prepare_face;
644 xftfont_driver.done_face = xftfont_done_face;
645 xftfont_driver.encode_char = xftfont_encode_char;
646 xftfont_driver.text_extents = xftfont_text_extents;
647 xftfont_driver.draw = xftfont_draw;
648 xftfont_driver.anchor_point = xftfont_anchor_point;
649 xftfont_driver.end_for_frame = xftfont_end_for_frame;
650 #ifdef HAVE_LIBOTF
651 #ifdef HAVE_M17N_FLT
652 xftfont_driver.shape = xftfont_shape;
653 #endif /* HAVE_M17N_FLT */
654 #endif /* HAVE_LIBOTF */
655
656 register_font_driver (&xftfont_driver, NULL);
657 }
658
659 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605
660 (do not change this comment) */