1 /* font-ft.c -- FreeType interface sub-module.
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 #include <sys/types.h>
35 #include "m17n-misc.h"
38 #include "internal-gui.h"
49 /* Having Xft2 means having fontconfig. */
50 #include <fontconfig/fontconfig.h>
52 int fontconfig_initialized = 0;
54 #endif /* not HAVE_XFT2 */
56 static FT_Library ft_library;
61 MSymbol weight, style, stretch;
64 static int ft_to_prop_size;
65 static MFTtoProp *ft_to_prop;
72 int otf_flag; /* This font 1: is OTF, 0: may be OTF, -1: is not OTF. */
81 #endif /* not HAVE_XFT2 */
84 /* List of FreeType fonts. Keys are family names, values are plists
85 contains fonts of the corresponding family. In the deeper plist,
86 keys are Mt, values are (MFTInfo *). */
87 static MPlist *ft_font_list;
89 /** Return 0 if NAME implies TrueType or OpenType fonts. Othersize
93 check_otf_filename (const char *name)
95 int len = strlen (name);
96 const char *ext = name + (len - 4);
99 || (memcmp (ext, ".ttf", 4)
100 && memcmp (ext, ".TTF", 4)
101 && memcmp (ext, ".otf", 4)
102 && memcmp (ext, ".OTF", 4)))
107 /** Setup members of FT_INFO from FT_FACE. Return the family name. */
110 set_font_info (FT_Face ft_face, MFTInfo *ft_info, MSymbol family)
112 MFont *font = &ft_info->font;
116 MPlist *charmap_list;
117 int unicode_bmp = -1, unicode_full = -1;
124 len = strlen (ft_face->family_name) + 1;
125 buf = (char *) alloca (len);
126 memcpy (buf, ft_face->family_name, len);
127 for (p = buf; *p; p++)
128 if (*p >= 'A' && *p <= 'Z')
130 family = msymbol (buf);
132 mfont__set_property (font, MFONT_FAMILY, family);
134 if (ft_face->style_name)
136 len = strlen (ft_face->style_name) + 1;
137 buf = (char *) alloca (len);
138 memcpy (buf, ft_face->style_name, len);
139 for (p = buf; *p; p++)
140 if (*p >= 'A' && *p <= 'Z')
142 style = msymbol (buf);
143 for (i = 0; i < ft_to_prop_size; i++)
144 if (ft_to_prop[i].ft_style == style)
146 mfont__set_property (font, MFONT_WEIGHT, ft_to_prop[i].weight);
147 mfont__set_property (font, MFONT_STYLE, ft_to_prop[i].style);
148 mfont__set_property (font, MFONT_STRETCH, ft_to_prop[i].stretch);
155 if (i == ft_to_prop_size)
157 mfont__set_property (font, MFONT_WEIGHT, msymbol ("medium"));
158 mfont__set_property (font, MFONT_STYLE, msymbol ("r"));
159 mfont__set_property (font, MFONT_STRETCH, msymbol ("normal"));
162 font->property[MFONT_TYPE] = MFONT_TYPE_FT + 1;
163 mfont__set_property (font, MFONT_ADSTYLE, msymbol (""));
165 charmap_list = mplist ();
166 mplist_add (charmap_list, Mt, (void *) -1);
167 for (i = 0; i < ft_face->num_charmaps; i++)
169 char registry_buf[16];
171 sprintf (registry_buf, "%d-%d",
172 ft_face->charmaps[i]->platform_id,
173 ft_face->charmaps[i]->encoding_id);
174 mplist_add (charmap_list, msymbol (registry_buf), (void *) i);
175 if (ft_face->charmaps[i]->platform_id == 0)
177 if (ft_face->charmaps[i]->encoding_id == 3)
179 else if (ft_face->charmaps[i]->encoding_id == 4)
182 else if (ft_face->charmaps[i]->platform_id == 3)
184 if (ft_face->charmaps[i]->encoding_id == 1)
186 else if (ft_face->charmaps[i]->encoding_id == 10)
189 else if (ft_face->charmaps[i]->platform_id == 1
190 && ft_face->charmaps[i]->encoding_id == 0)
191 mplist_add (charmap_list, msymbol ("apple-roman"), (void *) i);
193 if (unicode_bmp >= 0)
194 mplist_add (charmap_list, msymbol ("unicode-bmp"), (void *) unicode_bmp);
195 if (unicode_full >= 0)
196 mplist_add (charmap_list, msymbol ("unicode-full"), (void *) unicode_full);
198 ft_info->charmap_list = charmap_list;
205 add_font_list (MPlist *font_list)
209 MPLIST_DO (plist, font_list)
211 char *filename = MPLIST_VAL (plist);
214 if (FT_New_Face (ft_library, filename, 0, &ft_face) == 0)
216 if (ft_face->family_name && ((char *) ft_face->family_name)[0])
218 MSymbol family = MPLIST_KEY (plist);
222 MSTRUCT_CALLOC (ft_info, MERROR_FONT_FT);
223 ft_info->filename = filename;
224 ft_info->otf_flag = check_otf_filename (filename);
225 family = set_font_info (ft_face, ft_info, family);
226 p = mplist_get (ft_font_list, family);
230 mplist_add (ft_font_list, family, p);
232 mplist_add (p, family, ft_info);
234 FT_Done_Face (ft_face);
239 M17N_OBJECT_UNREF (font_list);
244 xft_list (MSymbol family)
258 fc_config = FcConfigGetCurrent ();
259 MPLIST_DO (plist, mfont_freetype_path)
260 if (MPLIST_STRING_P (plist)
261 && (pathname = MPLIST_STRING (plist))
262 && stat (pathname, &buf) == 0)
263 FcConfigAppFontAddDir (fc_config, (FcChar8 *) pathname);
266 pattern = FcPatternCreate ();
267 FcPatternAddString (pattern, FC_FAMILY, (FcChar8 *) (msymbol_name (family)));
268 os = FcObjectSetBuild (FC_FILE, NULL);
269 fs = FcFontList (fc_config, pattern, os);
273 for (i = 0; i < fs->nfont; i++)
277 FcPatternGetString (fs->fonts[i], FC_FILE, 0, &filename);
278 mplist_add (plist, family, strdup ((char *) filename));
280 FcFontSetDestroy (fs);
282 FcObjectSetDestroy (os);
283 FcPatternDestroy (pattern);
287 #else /* not HAVE_XFT2 */
291 MPlist *font_list = mplist (), *plist;
295 MPLIST_DO (plist, mfont_freetype_path)
296 if (MPLIST_STRING_P (plist)
297 && (pathname = MPLIST_STRING (plist))
298 && stat (pathname, &buf) == 0)
300 if (S_ISREG (buf.st_mode))
301 mplist_add (font_list, Mt, strdup (pathname));
302 else if (S_ISDIR (buf.st_mode))
304 int len = strlen (pathname);
306 DIR *dir = opendir (pathname);
312 strcpy (path, pathname);
313 strcpy (path + len, "/");
315 while ((dp = readdir (dir)) != NULL)
317 strcpy (path + len, dp->d_name);
318 mplist_add (font_list, Mt, strdup (path));
329 static MRealizedFont *ft_select (MFrame *, MFont *, MFont *, int);
330 static int ft_open (MRealizedFont *);
331 static void ft_close (MRealizedFont *);
332 static void ft_find_metric (MRealizedFont *, MGlyphString *, int, int);
333 static unsigned ft_encode_char (MRealizedFont *, int, unsigned);
334 static void ft_render (MDrawWindow, int, int, MGlyphString *,
335 MGlyph *, MGlyph *, int, MDrawRegion);
337 MFontDriver ft_driver =
338 { ft_select, ft_open, ft_close,
339 ft_find_metric, ft_encode_char, ft_render };
341 /* The FreeType font driver function LIST. */
343 static MRealizedFont *
344 ft_select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
349 MRealizedFont *rfont;
350 MSymbol family, registry;
354 family = FONT_PROPERTY (spec, MFONT_FAMILY);
356 family = FONT_PROPERTY (request, MFONT_FAMILY);
359 registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
360 if (registry == Mnil)
365 ft_font_list = mplist ();
366 plist = mplist_get (ft_font_list, family);
369 add_font_list (xft_list (family));
370 plist = mplist_get (ft_font_list, family);
372 mplist_add (ft_font_list, family, plist = mplist ());
374 #else /* not HAVE_XFT2 */
377 ft_font_list = mplist ();
378 add_font_list (ft_list ());
380 plist = mplist_get (ft_font_list, family);
383 #endif /* not HAVE_XFT2 */
385 MPLIST_DO (plist, plist)
387 MFTInfo *ft_info = MPLIST_VAL (plist);
388 MPlist *p = mplist_find_by_key (ft_info->charmap_list, registry);
393 /* We always ignore FOUNDRY. */
394 ft_info->font.property[MFONT_FOUNDRY] = spec->property[MFONT_FOUNDRY];
395 score = mfont__score (&ft_info->font, spec, request, limited_size);
398 || best_score > score))
409 MSTRUCT_CALLOC (rfont, MERROR_FONT_FT);
410 rfont->frame = frame;
412 rfont->request = *request;
413 rfont->font = best_font->font;
414 rfont->font.property[MFONT_SIZE] = request->property[MFONT_SIZE];
415 rfont->font.property[MFONT_REGISTRY] = spec->property[MFONT_REGISTRY];
416 rfont->score = best_score;
417 rfont->info = best_font;
418 rfont->driver = &ft_driver;
423 close_ft (void *object)
425 MFTInfo *ft_info = (MFTInfo *) object;
427 if (ft_info->ft_face)
428 FT_Done_Face (ft_info->ft_face);
430 if (ft_info->xft_info)
431 mwin__xft_close (ft_info->xft_info);
432 #endif /* HAVE_XFT2 */
435 OTF_close (ft_info->otf);
436 #endif /* HAVE_OTF */
440 /* The FreeType font driver function OPEN. */
443 ft_open (MRealizedFont *rfont)
446 MSymbol registry = FONT_PROPERTY (&rfont->font, MFONT_REGISTRY);
447 int mdebug_mask = MDEBUG_FONT;
450 M17N_OBJECT (ft_info, close_ft, MERROR_FONT_FT);
451 ft_info->font = ((MFTInfo *) rfont->info)->font;
452 ft_info->otf_flag = ((MFTInfo *) rfont->info)->otf_flag;
453 ft_info->filename = ((MFTInfo *) rfont->info)->filename;
454 ft_info->charmap_list = ((MFTInfo *) rfont->info)->charmap_list;
455 rfont->info = ft_info;
458 ft_info->ft_face = NULL;
459 if (FT_New_Face (ft_library, ft_info->filename, 0, &ft_info->ft_face))
461 if (registry == Mnil)
463 ft_info->charmap_index
464 = (int) mplist_get (((MFTInfo *) rfont->info)->charmap_list, registry);
465 if (ft_info->charmap_index >= 0
466 && FT_Set_Charmap (ft_info->ft_face,
467 ft_info->ft_face->charmaps[ft_info->charmap_index]))
469 size = rfont->font.property[MFONT_SIZE] / 10;
471 ft_info->xft_info = mwin__xft_open (rfont->frame, ft_info->filename, size);
472 if (! ft_info->xft_info)
474 #else /* not HAVE_XFT2 */
475 if (FT_Set_Pixel_Sizes (ft_info->ft_face, 0, size))
477 #endif /* not HAVE_XFT2 */
479 MDEBUG_PRINT1 (" [FT-FONT] o %s\n", ft_info->filename);
481 rfont->ascent = ft_info->ft_face->ascender >> 6;
482 rfont->descent = ft_info->ft_face->descender >> 6;
486 MDEBUG_PRINT1 (" [FT-FONT] x %s\n", ft_info->filename);
490 /* The FreeType font driver function CLOSE. */
493 ft_close (MRealizedFont *rfont)
495 M17N_OBJECT_UNREF (rfont->info);
498 /* The FreeType font driver function FIND_METRIC. */
501 ft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
504 MFTInfo *ft_info = (MFTInfo *) rfont->info;
505 FT_Face ft_face = ft_info->ft_face;
506 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
507 FT_Int32 load_flags = FT_LOAD_RENDER;
509 if (! gstring->anti_alias)
511 #ifdef FT_LOAD_TARGET_MONO
512 load_flags |= FT_LOAD_TARGET_MONO;
514 load_flags |= FT_LOAD_MONOCHROME;
518 for (; g != gend; g++)
520 if (g->code == MCHAR_INVALID_CODE)
522 unsigned unitsPerEm = ft_face->units_per_EM;
523 int size = rfont->font.property[MFONT_SIZE] / 10;
526 g->rbearing = ft_face->max_advance_width * size / unitsPerEm;
527 g->width = ft_face->max_advance_width * size / unitsPerEm;
528 g->ascent = ft_face->ascender * size / unitsPerEm;
529 g->descent = (- ft_face->descender) * size / unitsPerEm;
534 mwin__xft_get_metric (ft_info->xft_info, ft_info->ft_face, g);
535 #else /* not HAVE_XFT2 */
536 FT_Glyph_Metrics *metrics;
542 code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code);
544 FT_Load_Glyph (ft_face, code, FT_LOAD_RENDER);
545 metrics = &ft_face->glyph->metrics;
546 g->lbearing = (metrics->horiBearingX >> 6);
547 g->rbearing = (metrics->horiBearingX + metrics->width) >> 6;
548 g->width = metrics->horiAdvance >> 6;
549 g->ascent = metrics->horiBearingY >> 6;
550 g->descent = (metrics->height - metrics->horiBearingY) >> 6;
551 #endif /* not HAVE_XFT2 */
556 /* The FreeType font driver function ENCODE_CHAR. */
559 ft_encode_char (MRealizedFont *rfont, int c, unsigned ignored)
564 if (rfont->status == 0)
566 if (ft_open (rfont) < 0)
569 ft_info = (MFTInfo *) rfont->info;
570 code = FT_Get_Char_Index (ft_info->ft_face, (FT_ULong) c);
572 return MCHAR_INVALID_CODE;
573 return ((unsigned) c);
577 /* The FreeType font driver function RENDER. */
579 #define NUM_POINTS 0x1000
582 MDrawPoint points[NUM_POINTS];
587 ft_render (MDrawWindow win, int x, int y,
588 MGlyphString *gstring, MGlyph *from, MGlyph *to,
589 int reverse, MDrawRegion region)
593 MRealizedFace *rface = from->rface;
595 MFrame *frame = rface->frame;
596 FT_Int32 load_flags = FT_LOAD_RENDER;
599 MPointTable point_table[8];
600 #endif /* not HAVE_XFT2 */
605 /* It is assured that the all glyphs in the current range use the
606 same realized face. */
607 ft_info = (MFTInfo *) rface->rfont->info;
608 ft_face = ft_info->ft_face;
611 mwin__xft_render (win, x, y, gstring, from, to, reverse, region,
612 ft_info->xft_info, ft_face);
613 #else /* not HAVE_XFT2 */
614 if (! gstring->anti_alias)
616 #ifdef FT_LOAD_TARGET_MONO
617 load_flags |= FT_LOAD_TARGET_MONO;
619 load_flags |= FT_LOAD_MONOCHROME;
623 for (i = 0; i < 8; i++)
624 point_table[i].p = point_table[i].points;
626 for (g = from; g < to; x += g++->width)
637 code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code);
638 FT_Load_Glyph (ft_face, code, load_flags);
639 yoff = y - ft_face->glyph->bitmap_top + g->yoff;
640 bmp = ft_face->glyph->bitmap.buffer;
641 if (gstring->anti_alias)
642 for (i = 0; i < ft_face->glyph->bitmap.rows;
643 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
645 xoff = x + ft_face->glyph->bitmap_left + g->xoff;
646 for (j = 0; j < ft_face->glyph->bitmap.width; j++, xoff++)
648 intensity = bmp[j] >> 5;
651 ptable = point_table + intensity;
655 if (ptable->p - ptable->points == NUM_POINTS)
657 mwin__draw_points (frame, win, rface,
658 reverse ? 7 - intensity : intensity,
659 ptable->points, NUM_POINTS, region);
660 ptable->p = ptable->points;
666 for (i = 0; i < ft_face->glyph->bitmap.rows;
667 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
669 xoff = x + ft_face->glyph->bitmap_left + g->xoff;
670 for (j = 0; j < ft_face->glyph->bitmap.width; j++, xoff++)
672 intensity = bmp[j / 8] & (1 << (7 - (j % 8)));
675 ptable = point_table;
679 if (ptable->p - ptable->points == NUM_POINTS)
681 mwin__draw_points (frame, win, rface,
683 ptable->points, NUM_POINTS, region);
684 ptable->p = ptable->points;
691 if (gstring->anti_alias)
693 for (i = 1; i < 8; i++)
694 if (point_table[i].p != point_table[i].points)
695 mwin__draw_points (frame, win, rface, reverse ? 7 - i : i,
696 point_table[i].points,
697 point_table[i].p - point_table[i].points, region);
701 if (point_table[0].p != point_table[0].points)
702 mwin__draw_points (frame, win, rface, reverse ? 0 : 7,
703 point_table[0].points,
704 point_table[0].p - point_table[0].points, region);
706 #endif /* not HAVE_XFT2 */
716 char *weight, *style, *stretch;
717 } ft_to_prop_name[] =
718 { { "regular", "medium", "r", "normal" },
719 { "italic", "medium", "i", "normal" },
720 { "bold", "bold", "r", "normal" },
721 { "bold italic", "bold", "i", "normal" },
722 { "narrow", "medium", "r", "condensed" },
723 { "narrow italic", "medium", "i", "condensed" },
724 { "narrow bold", "bold", "r", "condensed" },
725 { "narrow bold italic", "bold", "i", "condensed" },
726 { "black", "black", "r", "normal" },
727 { "black italic", "black", "i", "normal" },
728 { "oblique", "medium", "o", "normal" },
729 { "boldoblique", "bold", "o", "normal" } };
732 if (FT_Init_FreeType (&ft_library) != 0)
733 MERROR (MERROR_FONT_FT, -1);
735 ft_to_prop_size = sizeof (ft_to_prop_name) / sizeof (ft_to_prop_name[0]);
736 MTABLE_MALLOC (ft_to_prop, ft_to_prop_size, MERROR_FONT_FT);
737 for (i = 0; i < ft_to_prop_size; i++)
739 ft_to_prop[i].ft_style = msymbol (ft_to_prop_name[i].ft_style);
740 ft_to_prop[i].weight = msymbol (ft_to_prop_name[i].weight);
741 ft_to_prop[i].style = msymbol (ft_to_prop_name[i].style);
742 ft_to_prop[i].stretch = msymbol (ft_to_prop_name[i].stretch);
745 mfont__driver_list[MFONT_TYPE_FT] = &ft_driver;
757 MPLIST_DO (plist, ft_font_list)
759 MPLIST_DO (p, MPLIST_VAL (plist))
761 MFTInfo *ft_info = (MFTInfo *) MPLIST_VAL (p);
762 free (ft_info->filename);
763 M17N_OBJECT_UNREF (ft_info->charmap_list);
766 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
768 M17N_OBJECT_UNREF (ft_font_list);
772 FT_Done_FreeType (ft_library);
777 mfont__ft_drive_otf (MGlyphString *gstring, int from, int to,
778 MRealizedFont *rfont,
779 MSymbol script, MSymbol langsys,
780 MSymbol gsub_features, MSymbol gpos_features)
788 OTF_GlyphString otf_gstring;
790 char *script_name, *language_name;
791 char *gsub_feature_names, *gpos_feature_names;
792 int from_pos, to_pos;
798 ft_info = (MFTInfo *) rfont->info;
799 if (ft_info->otf_flag < 0)
802 if (! otf && (otf = OTF_open (ft_info->filename)))
804 if (OTF_get_table (otf, "head") < 0
805 || (OTF_check_table (otf, "GSUB") < 0
806 && OTF_check_table (otf, "GPOS") < 0))
809 ft_info->otf_flag = -1;
816 script_name = msymbol_name (script);
817 language_name = langsys != Mnil ? msymbol_name (langsys) : NULL;
819 = (gsub_features == Mt ? "*"
820 : gsub_features == Mnil ? NULL
821 : msymbol_name (gsub_features));
823 = (gpos_features == Mt ? "*"
824 : gpos_features == Mnil ? NULL
825 : msymbol_name (gpos_features));
827 g = gstring->glyphs[from];
830 for (i = from + 1; i < to; i++)
832 if (from_pos > gstring->glyphs[i].pos)
833 from_pos = gstring->glyphs[i].pos;
834 if (to_pos < gstring->glyphs[i].to)
835 to_pos = gstring->glyphs[i].to;
838 unitsPerEm = otf->head->unitsPerEm;
839 otf_gstring.size = otf_gstring.used = len;
840 otf_gstring.glyphs = (OTF_Glyph *) alloca (sizeof (OTF_Glyph) * len);
841 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
842 for (i = 0; i < len; i++)
844 if (gstring->glyphs[from + i].otf_encoded)
846 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].c;
847 otf_gstring.glyphs[i].glyph_id = gstring->glyphs[from + i].code;
851 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].code;
855 if (OTF_drive_tables (otf, &otf_gstring, script_name, language_name,
856 gsub_feature_names, gpos_feature_names) < 0)
860 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++, otfg++)
862 g.combining_code = 0;
866 g.code = otfg->glyph_id;
867 switch (otfg->positioning_type)
871 int off_x = 128, off_y = 128;
873 if (otfg->f.f1.format & OTF_XPlacement)
874 off_x = ((double) (otfg->f.f1.value->XPlacement)
875 * 100 / unitsPerEm + 128);
876 if (otfg->f.f1.format & OTF_YPlacement)
877 off_y = ((double) (otfg->f.f1.value->YPlacement)
878 * 100 / unitsPerEm + 128);
880 = MAKE_COMBINING_CODE (3, 2, 3, 0, off_y, off_x);
881 if ((otfg->f.f1.format & OTF_XAdvance)
882 || (otfg->f.f1.format & OTF_YAdvance))
887 /* Not yet supported. */
893 off_x = ((double) (otfg->f.f4.base_anchor->XCoordinate
894 - otfg->f.f4.mark_anchor->XCoordinate)
895 * 100 / unitsPerEm + 128);
896 off_y = ((double) (otfg->f.f4.base_anchor->YCoordinate
897 - otfg->f.f4.mark_anchor->YCoordinate)
898 * 100 / unitsPerEm + 128);
900 = MAKE_COMBINING_CODE (3, 0, 3, 0, off_y, off_x);
904 /* Not yet supported. */
906 default: /* i.e case 6 */
907 /* Not yet supported. */
917 MLIST_APPEND1 (gstring, glyphs, g, MERROR_FONT_OTF);
922 #endif /* HAVE_OTF */
923 for (i = 0; i < len; i++)
925 g = gstring->glyphs[from + i];
926 MLIST_APPEND1 (gstring, glyphs, g, MERROR_FONT_OTF);
932 mfont__ft_decode_otf (MGlyph *g)
935 MFTInfo *ft_info = (MFTInfo *) g->rface->rfont->info;
936 int c = OTF_get_unicode (ft_info->otf, (OTF_GlyphID) g->code);
939 #else /* not HAVE_OTF */
941 #endif /* not HAVE_OTF */
944 #else /* not HAVE_FREETYPE */
957 #endif /* HAVE_FREETYPE */