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"
39 #include "internal-gui.h"
45 #include <freetype/ftbdf.h>
47 #ifdef HAVE_FONTCONFIG
48 #include <fontconfig/fontconfig.h>
50 int fontconfig_initialized = 0;
52 #endif /* not HAVE_FONTCONFIG */
54 static MSymbol Municode_bmp, Municode_full, Miso10646_1, Miso8859_1;
56 static FT_Library ft_library;
61 MSymbol weight, style, stretch;
64 static int ft_to_prop_size;
65 static MFTtoProp *ft_to_prop;
67 /** List of FreeType fonts. Keys are family names, values are plists
68 contains fonts of the corresponding family. In the deeper plist,
69 keys are Mt, values are (MFTInfo *). */
70 static MPlist *ft_font_list;
72 static int all_fonts_scaned;
74 /** Return 0 if NAME implies TrueType or OpenType fonts. Othersize
78 check_otf_filename (const char *name)
80 int len = strlen (name);
81 const char *ext = name + (len - 4);
84 || (memcmp (ext, ".ttf", 4)
85 && memcmp (ext, ".TTF", 4)
86 && memcmp (ext, ".otf", 4)
87 && memcmp (ext, ".OTF", 4)))
92 /** Setup members of FT_INFO from FT_FACE. Return the family name. */
95 set_font_info (FT_Face ft_face, MFTInfo *ft_info, MSymbol family)
97 MFont *font = &ft_info->font;
101 MPlist *charmap_list;
102 int unicode_bmp = -1, unicode_full = -1, unicode = -1;
109 len = strlen (ft_face->family_name) + 1;
110 buf = (char *) alloca (len);
111 memcpy (buf, ft_face->family_name, len);
112 for (p = buf; *p; p++)
113 if (*p >= 'A' && *p <= 'Z')
115 family = msymbol (buf);
117 mfont__set_property (font, MFONT_FAMILY, family);
119 if (ft_face->style_name)
121 len = strlen (ft_face->style_name) + 1;
122 buf = (char *) alloca (len);
123 memcpy (buf, ft_face->style_name, len);
124 for (p = buf; *p; p++)
125 if (*p >= 'A' && *p <= 'Z')
127 style = msymbol (buf);
128 for (i = 0; i < ft_to_prop_size; i++)
129 if (ft_to_prop[i].ft_style == style)
131 mfont__set_property (font, MFONT_WEIGHT, ft_to_prop[i].weight);
132 mfont__set_property (font, MFONT_STYLE, ft_to_prop[i].style);
133 mfont__set_property (font, MFONT_STRETCH, ft_to_prop[i].stretch);
140 if (i == ft_to_prop_size)
142 mfont__set_property (font, MFONT_WEIGHT, msymbol ("medium"));
143 mfont__set_property (font, MFONT_STYLE, msymbol ("r"));
144 mfont__set_property (font, MFONT_STRETCH, msymbol ("normal"));
147 mfont__set_property (font, MFONT_ADSTYLE, msymbol (""));
149 charmap_list = mplist ();
150 mplist_add (charmap_list, Mt, (void *) -1);
151 for (i = 0; i < ft_face->num_charmaps; i++)
153 char registry_buf[16];
156 sprintf (registry_buf, "%d-%d",
157 ft_face->charmaps[i]->platform_id,
158 ft_face->charmaps[i]->encoding_id);
159 registry = msymbol (registry_buf);
160 mplist_add (charmap_list, registry, (void *) i);
162 if (ft_face->charmaps[i]->platform_id == 0)
164 if (ft_face->charmaps[i]->encoding_id == 3)
166 else if (ft_face->charmaps[i]->encoding_id == 4)
169 else if (ft_face->charmaps[i]->platform_id == 3)
171 if (ft_face->charmaps[i]->encoding_id == 1)
173 else if (ft_face->charmaps[i]->encoding_id == 10)
176 else if (ft_face->charmaps[i]->platform_id == 1
177 && ft_face->charmaps[i]->encoding_id == 0)
178 mplist_add (charmap_list, msymbol ("apple-roman"), (void *) i);
180 if (unicode_full >= 0)
182 mplist_add (charmap_list, Municode_full, (void *) unicode_full);
183 mplist_add (charmap_list, Municode_bmp, (void *) unicode_full);
184 mplist_add (charmap_list, Miso10646_1, (void *) unicode_full);
185 unicode = unicode_full;
187 else if (unicode_bmp >= 0)
189 mplist_add (charmap_list, Municode_bmp, (void *) unicode_bmp);
190 mplist_add (charmap_list, Miso10646_1, (void *) unicode_bmp);
191 unicode = unicode_bmp;
195 FT_Set_Charmap (ft_face, ft_face->charmaps[unicode]);
196 for (i = 255; i >= 32; i--)
200 if (FT_Get_Char_Index (ft_face, (FT_ULong) i) == 0)
204 mplist_add (charmap_list, Miso8859_1, (void *) unicode);
207 ft_info->charmap_list = charmap_list;
209 if (! FT_IS_SCALABLE (ft_face))
211 BDF_PropertyRec prop;
213 FT_Get_BDF_Property (ft_face, "PIXEL_SIZE", &prop);
214 font->property[MFONT_SIZE] = prop.u.integer * 10;
215 FT_Get_BDF_Property (ft_face, "RESOLUTION_Y", &prop);
216 font->property[MFONT_RESY] = prop.u.integer;
224 close_ft (void *object)
226 MFTInfo *ft_info = object;
228 if (ft_info->ft_face)
230 if (ft_info->extra_info)
231 M17N_OBJECT_UNREF (ft_info->extra_info);
232 FT_Done_Face (ft_info->ft_face);
235 OTF_close (ft_info->otf);
236 #endif /* HAVE_OTF */
238 free (ft_info->filename);
239 M17N_OBJECT_UNREF (ft_info->charmap_list);
244 add_font_info (char *filename, MSymbol family)
247 BDF_PropertyRec prop;
248 MFTInfo *ft_info = NULL;
250 if (FT_New_Face (ft_library, filename, 0, &ft_face) == 0)
252 if (FT_IS_SCALABLE (ft_face)
253 || FT_Get_BDF_Property (ft_face, "PIXEL_SIZE", &prop) == 0)
258 M17N_OBJECT (ft_info, close_ft, MERROR_FONT_FT);
259 ft_info->filename = strdup (filename);
260 ft_info->otf_flag = check_otf_filename (filename);
261 fam = set_font_info (ft_face, ft_info, family);
262 plist = mplist_get (ft_font_list, fam);
266 mplist_add (ft_font_list, fam, plist);
268 mplist_add (plist, fam, ft_info);
270 FT_Done_Face (ft_face);
274 #ifdef HAVE_FONTCONFIG
277 fc_list (MSymbol family)
291 fc_config = FcConfigGetCurrent ();
292 MPLIST_DO (plist, mfont_freetype_path)
293 if (MPLIST_STRING_P (plist)
294 && (pathname = MPLIST_STRING (plist))
295 && stat (pathname, &buf) == 0)
296 FcConfigAppFontAddDir (fc_config, (FcChar8 *) pathname);
299 pattern = FcPatternCreate ();
301 FcPatternAddString (pattern, FC_FAMILY,
302 (FcChar8 *) (msymbol_name (family)));
303 os = FcObjectSetBuild (FC_FILE, FC_FOUNDRY, FC_FAMILY, FC_STYLE, FC_PIXEL_SIZE, NULL);
304 fs = FcFontList (fc_config, pattern, os);
307 for (i = 0; i < fs->nfont; i++)
311 FcPatternGetString (fs->fonts[i], FC_FILE, 0, (FcChar8 **) &filename);
312 add_font_info (filename, family);
314 FcFontSetDestroy (fs);
316 FcObjectSetDestroy (os);
317 FcPatternDestroy (pattern);
320 #else /* not HAVE_FONTCONFIG */
329 MPLIST_DO (plist, mfont_freetype_path)
330 if (MPLIST_STRING_P (plist)
331 && (pathname = MPLIST_STRING (plist))
332 && stat (pathname, &buf) == 0)
334 if (S_ISREG (buf.st_mode))
335 add_font_info (pathname, Mnil);
336 else if (S_ISDIR (buf.st_mode))
338 int len = strlen (pathname);
340 DIR *dir = opendir (pathname);
345 strcpy (path, pathname);
346 strcpy (path + len, "/");
348 while ((dp = readdir (dir)) != NULL)
350 strcpy (path + len, dp->d_name);
351 add_font_info (path, Mnil);
359 #endif /* not HAVE_FONTCONFIG */
361 /* The FreeType font driver function SELECT. */
363 static MRealizedFont *
364 ft_select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
369 MRealizedFont *rfont;
370 MSymbol family, registry;
374 family = FONT_PROPERTY (spec, MFONT_FAMILY);
376 family = FONT_PROPERTY (request, MFONT_FAMILY);
377 registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
378 if (registry == Mnil)
382 ft_font_list = mplist ();
383 #ifdef HAVE_FONTCONFIG
386 plist = mplist_get (ft_font_list, family);
390 plist = mplist_get (ft_font_list, family);
393 mplist_add (ft_font_list, family, plist = mplist ());
400 if (! all_fonts_scaned)
403 all_fonts_scaned = 1;
406 #else /* not HAVE_FONTCONFIG */
407 if (! all_fonts_scaned)
410 all_fonts_scaned = 1;
414 plist = mplist_get (ft_font_list, family);
418 #endif /* not HAVE_FONTCONFIG */
421 plist = MPLIST_VAL (ft_font_list);
424 MPLIST_DO (pl, plist)
426 MFTInfo *ft_info = MPLIST_VAL (pl);
429 if (! mplist_find_by_key (ft_info->charmap_list, registry))
431 /* We always ignore FOUNDRY. */
432 ft_info->font.property[MFONT_FOUNDRY] = spec->property[MFONT_FOUNDRY];
433 score = mfont__score (&ft_info->font, spec, request, limited_size);
436 || best_score > score))
446 plist = MPLIST_NEXT (plist);
447 if (! MPLIST_TAIL_P (plist))
453 MSTRUCT_CALLOC (rfont, MERROR_FONT_FT);
454 rfont->frame = frame;
456 rfont->request = *request;
457 rfont->font = best_font->font;
458 rfont->font.property[MFONT_SIZE] = request->property[MFONT_SIZE];
459 rfont->font.property[MFONT_REGISTRY] = spec->property[MFONT_REGISTRY];
460 rfont->score = best_score;
461 rfont->info = best_font;
462 M17N_OBJECT_REF (best_font);
467 /* The FreeType font driver function OPEN. */
470 ft_open (MRealizedFont *rfont)
472 MFTInfo *base = rfont->info, *ft_info;
473 MSymbol registry = FONT_PROPERTY (&rfont->font, MFONT_REGISTRY);
474 int mdebug_mask = MDEBUG_FONT;
477 M17N_OBJECT (ft_info, close_ft, MERROR_FONT_FT);
478 ft_info->font = base->font;
479 ft_info->filename = strdup (base->filename);
480 ft_info->otf_flag = base->otf_flag;
481 ft_info->charmap_list = base->charmap_list;
482 M17N_OBJECT_REF (ft_info->charmap_list);
483 M17N_OBJECT_UNREF (base);
484 rfont->info = ft_info;
487 ft_info->ft_face = NULL;
488 if (FT_New_Face (ft_library, ft_info->filename, 0, &ft_info->ft_face))
490 if (registry == Mnil)
492 ft_info->charmap_index
493 = (int) mplist_get (((MFTInfo *) rfont->info)->charmap_list, registry);
494 if (ft_info->charmap_index >= 0
495 && FT_Set_Charmap (ft_info->ft_face,
496 ft_info->ft_face->charmaps[ft_info->charmap_index]))
498 size = rfont->font.property[MFONT_SIZE] / 10;
499 if (FT_Set_Pixel_Sizes (ft_info->ft_face, 0, size))
502 MDEBUG_PRINT1 (" [FT-FONT] o %s\n", ft_info->filename);
504 rfont->ascent = ft_info->ft_face->ascender >> 6;
505 rfont->descent = - (ft_info->ft_face->descender >> 6);
509 MDEBUG_PRINT1 (" [FT-FONT] x %s\n", ft_info->filename);
510 if (ft_info->ft_face)
511 FT_Done_Face (ft_info->ft_face);
512 M17N_OBJECT_UNREF (ft_info->charmap_list);
513 free (ft_info->filename);
519 /* The FreeType font driver function FIND_METRIC. */
522 ft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
525 MFTInfo *ft_info = (MFTInfo *) rfont->info;
526 FT_Face ft_face = ft_info->ft_face;
527 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
528 FT_Int32 load_flags = FT_LOAD_RENDER;
530 #ifdef FT_LOAD_TARGET_MONO
531 load_flags |= FT_LOAD_TARGET_MONO;
533 load_flags |= FT_LOAD_MONOCHROME;
536 for (; g != gend; g++)
538 if (g->code == MCHAR_INVALID_CODE)
540 if (FT_IS_SCALABLE (ft_face))
542 unsigned unitsPerEm = ft_face->units_per_EM;
543 int size = rfont->font.property[MFONT_SIZE] / 10;
546 g->rbearing = ft_face->max_advance_width * size / unitsPerEm;
547 g->width = ft_face->max_advance_width * size / unitsPerEm;
548 g->ascent = ft_face->ascender * size / unitsPerEm;
549 g->descent = (- ft_face->descender) * size / unitsPerEm;
553 BDF_PropertyRec prop;
556 g->rbearing = g->width = ft_face->available_sizes->width;
557 if (FT_Get_BDF_Property (ft_face, "ASCENT", &prop) == 0)
559 g->ascent = prop.u.integer;
560 FT_Get_BDF_Property (ft_face, "DESCENT", &prop);
561 g->descent = prop.u.integer;
565 g->ascent = ft_face->available_sizes->height;
572 FT_Glyph_Metrics *metrics;
578 code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code);
580 FT_Load_Glyph (ft_face, code, FT_LOAD_RENDER);
581 metrics = &ft_face->glyph->metrics;
582 g->lbearing = (metrics->horiBearingX >> 6);
583 g->rbearing = (metrics->horiBearingX + metrics->width) >> 6;
584 g->width = metrics->horiAdvance >> 6;
585 g->ascent = metrics->horiBearingY >> 6;
586 g->descent = (metrics->height - metrics->horiBearingY) >> 6;
591 /* The FreeType font driver function ENCODE_CHAR. */
594 ft_encode_char (MRealizedFont *rfont, int c, unsigned ignored)
599 if (rfont->status == 0)
601 if ((rfont->driver->open) (rfont) < 0)
604 ft_info = (MFTInfo *) rfont->info;
605 code = FT_Get_Char_Index (ft_info->ft_face, (FT_ULong) c);
607 return MCHAR_INVALID_CODE;
608 return ((unsigned) c);
612 /* The FreeType font driver function RENDER. */
614 #define NUM_POINTS 0x1000
617 MDrawPoint points[NUM_POINTS];
622 ft_render (MDrawWindow win, int x, int y,
623 MGlyphString *gstring, MGlyph *from, MGlyph *to,
624 int reverse, MDrawRegion region)
628 MRealizedFace *rface = from->rface;
629 MFrame *frame = rface->frame;
630 FT_Int32 load_flags = FT_LOAD_RENDER;
633 MPointTable point_table[8];
638 /* It is assured that the all glyphs in the current range use the
639 same realized face. */
640 ft_info = (MFTInfo *) rface->rfont->info;
641 ft_face = ft_info->ft_face;
643 if (! gstring->anti_alias)
645 #ifdef FT_LOAD_TARGET_MONO
646 load_flags |= FT_LOAD_TARGET_MONO;
648 load_flags |= FT_LOAD_MONOCHROME;
652 for (i = 0; i < 8; i++)
653 point_table[i].p = point_table[i].points;
655 for (g = from; g < to; x += g++->width)
667 code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code);
668 FT_Load_Glyph (ft_face, code, load_flags);
669 yoff = y - ft_face->glyph->bitmap_top + g->yoff;
670 bmp = ft_face->glyph->bitmap.buffer;
671 width = ft_face->glyph->bitmap.width;
672 pitch = ft_face->glyph->bitmap.pitch;
673 if (! gstring->anti_alias)
678 if (gstring->anti_alias)
679 for (i = 0; i < ft_face->glyph->bitmap.rows;
680 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
682 xoff = x + ft_face->glyph->bitmap_left + g->xoff;
683 for (j = 0; j < width; j++, xoff++)
685 intensity = bmp[j] >> 5;
688 ptable = point_table + intensity;
692 if (ptable->p - ptable->points == NUM_POINTS)
694 (*frame->driver->draw_points)
696 reverse ? 7 - intensity : intensity,
697 ptable->points, NUM_POINTS, region);
698 ptable->p = ptable->points;
704 for (i = 0; i < ft_face->glyph->bitmap.rows;
705 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
707 xoff = x + ft_face->glyph->bitmap_left + g->xoff;
708 for (j = 0; j < width; j++, xoff++)
710 intensity = bmp[j / 8] & (1 << (7 - (j % 8)));
713 ptable = point_table;
717 if (ptable->p - ptable->points == NUM_POINTS)
719 (*frame->driver->draw_points) (frame, win, rface,
721 ptable->points, NUM_POINTS, region);
722 ptable->p = ptable->points;
729 if (gstring->anti_alias)
731 for (i = 1; i < 8; i++)
732 if (point_table[i].p != point_table[i].points)
733 (*frame->driver->draw_points) (frame, win, rface, reverse ? 7 - i : i,
734 point_table[i].points,
735 point_table[i].p - point_table[i].points, region);
739 if (point_table[0].p != point_table[0].points)
740 (*frame->driver->draw_points) (frame, win, rface, reverse ? 0 : 7,
741 point_table[0].points,
742 point_table[0].p - point_table[0].points, region);
749 MFontDriver mfont__ft_driver =
750 { ft_select, ft_open, ft_find_metric, ft_encode_char, ft_render };
757 char *weight, *style, *stretch;
758 } ft_to_prop_name[] =
759 { { "regular", "medium", "r", "normal" },
760 { "italic", "medium", "i", "normal" },
761 { "bold", "bold", "r", "normal" },
762 { "bold italic", "bold", "i", "normal" },
763 { "narrow", "medium", "r", "condensed" },
764 { "narrow italic", "medium", "i", "condensed" },
765 { "narrow bold", "bold", "r", "condensed" },
766 { "narrow bold italic", "bold", "i", "condensed" },
767 { "black", "black", "r", "normal" },
768 { "black italic", "black", "i", "normal" },
769 { "oblique", "medium", "o", "normal" },
770 { "boldoblique", "bold", "o", "normal" } };
773 if (FT_Init_FreeType (&ft_library) != 0)
774 MERROR (MERROR_FONT_FT, -1);
776 ft_to_prop_size = sizeof (ft_to_prop_name) / sizeof (ft_to_prop_name[0]);
777 MTABLE_MALLOC (ft_to_prop, ft_to_prop_size, MERROR_FONT_FT);
778 for (i = 0; i < ft_to_prop_size; i++)
780 ft_to_prop[i].ft_style = msymbol (ft_to_prop_name[i].ft_style);
781 ft_to_prop[i].weight = msymbol (ft_to_prop_name[i].weight);
782 ft_to_prop[i].style = msymbol (ft_to_prop_name[i].style);
783 ft_to_prop[i].stretch = msymbol (ft_to_prop_name[i].stretch);
786 Municode_bmp = msymbol ("unicode-bmp");
787 Municode_full = msymbol ("unicode-full");
788 Miso10646_1 = msymbol ("iso10646-1");
789 Miso8859_1 = msymbol ("iso8859-1");
801 MPLIST_DO (plist, ft_font_list)
803 MPLIST_DO (p, MPLIST_VAL (plist))
805 MFTInfo *ft_info = MPLIST_VAL (p);
807 M17N_OBJECT_UNREF (ft_info);
809 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
811 M17N_OBJECT_UNREF (ft_font_list);
815 FT_Done_FreeType (ft_library);
816 all_fonts_scaned = 0;
820 #ifdef HAVE_FONTCONFIG
822 mfont__ft_parse_name (char *name, MFont *font)
824 FcPattern *pat = FcNameParse (name);
831 if ((result = FcPatternGetString (pat, FC_FOUNDRY, 0, &str)) == FcResultMatch)
832 mfont__set_property (font, MFONT_FOUNDRY, msymbol ((char *) str));
833 if ((result = FcPatternGetString (pat, FC_FAMILY, 0, &str)) == FcResultMatch)
834 mfont__set_property (font, MFONT_FAMILY, msymbol ((char *) str));
835 if ((result = FcPatternGetString (pat, FC_STYLE, 0, &str)) == FcResultMatch)
837 MSymbol style = msymbol ((char *) str);
840 for (i = 0; i < ft_to_prop_size; i++)
841 if (ft_to_prop[i].ft_style == style)
843 mfont__set_property (font, MFONT_WEIGHT, ft_to_prop[i].weight);
844 mfont__set_property (font, MFONT_STYLE, ft_to_prop[i].style);
845 mfont__set_property (font, MFONT_STRETCH, ft_to_prop[i].stretch);
849 if ((result = FcPatternGetDouble (pat, FC_PIXEL_SIZE, 0, &size))
851 font->property[MFONT_SIZE] = size * 10;
852 FcPatternDestroy (pat);
857 mfont__ft_unparse_name (MFont *font)
859 FcPattern *pat = FcPatternCreate ();
860 MSymbol sym, weight, style, stretch;
864 if ((sym = (MSymbol) FONT_PROPERTY (font, MFONT_FOUNDRY)) != Mnil)
865 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) MSYMBOL_NAME (sym));
866 if ((sym = (MSymbol) FONT_PROPERTY (font, MFONT_FAMILY)) != Mnil)
867 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) MSYMBOL_NAME (sym));
868 if ((weight = (MSymbol) FONT_PROPERTY (font, MFONT_WEIGHT)) == Mnil)
869 weight = msymbol ("medium");
870 if ((style = (MSymbol) FONT_PROPERTY (font, MFONT_STYLE)) == Mnil)
871 style = msymbol ("r");
872 if ((stretch = (MSymbol) FONT_PROPERTY (font, MFONT_STRETCH)) == Mnil)
873 stretch = msymbol ("normal");
874 for (i = 0; i < ft_to_prop_size; i++)
875 if (ft_to_prop[i].weight == weight
876 && ft_to_prop[i].style == style
877 && ft_to_prop[i].stretch == stretch)
878 FcPatternAddString (pat, FC_STYLE,
879 (FcChar8 *) MSYMBOL_NAME (ft_to_prop[i].ft_style));
880 name = (char *) FcNameUnparse (pat);
881 FcPatternDestroy (pat);
884 #endif /* HAVE_FONTCONFIG */
887 mfont__ft_drive_otf (MGlyphString *gstring, int from, int to,
888 MRealizedFont *rfont,
889 MSymbol script, MSymbol langsys,
890 MSymbol gsub_features, MSymbol gpos_features)
898 OTF_GlyphString otf_gstring;
900 char *script_name, *language_name;
901 char *gsub_feature_names, *gpos_feature_names;
902 int from_pos, to_pos;
908 ft_info = (MFTInfo *) rfont->info;
909 if (ft_info->otf_flag < 0)
912 if (! otf && (otf = OTF_open (ft_info->filename)))
914 if (OTF_get_table (otf, "head") < 0
915 || (OTF_check_table (otf, "GSUB") < 0
916 && OTF_check_table (otf, "GPOS") < 0))
919 ft_info->otf_flag = -1;
926 script_name = msymbol_name (script);
927 language_name = langsys != Mnil ? msymbol_name (langsys) : NULL;
929 = (gsub_features == Mt ? "*"
930 : gsub_features == Mnil ? NULL
931 : msymbol_name (gsub_features));
933 = (gpos_features == Mt ? "*"
934 : gpos_features == Mnil ? NULL
935 : msymbol_name (gpos_features));
937 g = gstring->glyphs[from];
940 for (i = from + 1; i < to; i++)
942 if (from_pos > gstring->glyphs[i].pos)
943 from_pos = gstring->glyphs[i].pos;
944 if (to_pos < gstring->glyphs[i].to)
945 to_pos = gstring->glyphs[i].to;
948 unitsPerEm = otf->head->unitsPerEm;
949 otf_gstring.size = otf_gstring.used = len;
950 otf_gstring.glyphs = (OTF_Glyph *) alloca (sizeof (OTF_Glyph) * len);
951 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
952 for (i = 0; i < len; i++)
954 if (gstring->glyphs[from + i].otf_encoded)
956 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].c;
957 otf_gstring.glyphs[i].glyph_id = gstring->glyphs[from + i].code;
961 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].code;
965 if (OTF_drive_tables (otf, &otf_gstring, script_name, language_name,
966 gsub_feature_names, gpos_feature_names) < 0)
970 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++, otfg++)
972 g.combining_code = 0;
976 g.code = otfg->glyph_id;
977 switch (otfg->positioning_type)
981 int off_x = 128, off_y = 128;
983 if (otfg->f.f1.format & OTF_XPlacement)
984 off_x = ((double) (otfg->f.f1.value->XPlacement)
985 * 100 / unitsPerEm + 128);
986 if (otfg->f.f1.format & OTF_YPlacement)
987 off_y = ((double) (otfg->f.f1.value->YPlacement)
988 * 100 / unitsPerEm + 128);
990 = MAKE_COMBINING_CODE (3, 2, 3, 0, off_y, off_x);
991 if ((otfg->f.f1.format & OTF_XAdvance)
992 || (otfg->f.f1.format & OTF_YAdvance))
997 /* Not yet supported. */
1003 off_x = ((double) (otfg->f.f4.base_anchor->XCoordinate
1004 - otfg->f.f4.mark_anchor->XCoordinate)
1005 * 100 / unitsPerEm + 128);
1006 off_y = ((double) (otfg->f.f4.base_anchor->YCoordinate
1007 - otfg->f.f4.mark_anchor->YCoordinate)
1008 * 100 / unitsPerEm + 128);
1010 = MAKE_COMBINING_CODE (3, 0, 3, 0, off_y, off_x);
1014 /* Not yet supported. */
1016 default: /* i.e case 6 */
1017 /* Not yet supported. */
1027 MLIST_APPEND1 (gstring, glyphs, g, MERROR_FONT_OTF);
1032 #endif /* HAVE_OTF */
1033 for (i = 0; i < len; i++)
1035 g = gstring->glyphs[from + i];
1036 MLIST_APPEND1 (gstring, glyphs, g, MERROR_FONT_OTF);
1042 mfont__ft_decode_otf (MGlyph *g)
1045 MFTInfo *ft_info = (MFTInfo *) g->rface->rfont->info;
1046 int c = OTF_get_unicode (ft_info->otf, (OTF_GlyphID) g->code);
1048 return (c ? c : -1);
1049 #else /* not HAVE_OTF */
1051 #endif /* not HAVE_OTF */
1054 #endif /* HAVE_FREETYPE */