2 * The font parser using the FreeType library version 2.
8 #include "../../config.h"
15 #include <sys/types.h>
16 #include <freetype/freetype.h>
17 #include <freetype/ftglyph.h>
18 #include <freetype/ftsnames.h>
19 #include <freetype/ttnameid.h>
20 #include <freetype/ftoutln.h>
24 /* prototypes of call entries */
25 static void openfont(char *fname, char *arg);
26 static void closefont( void);
27 static int getnglyphs ( void);
28 static int glnames( GLYPH *glyph_list);
29 static void glmetrics( GLYPH *glyph_list);
30 static int glenc( GLYPH *glyph_list, int *encoding, int *unimap);
31 static void fnmetrics( struct font_metrics *fm);
32 static void glpath( int glyphno, GLYPH *glyph_list);
33 static void kerning( GLYPH *glyph_list);
37 /* front-end descriptor */
38 struct frontsw freetype_sw = {
40 /*descr*/ "based on the FreeType library",
41 /*suffix*/ { "ttf", "otf", "pfa", "pfb" },
44 /*nglyphs*/ getnglyphs,
46 /*glmetrics*/ glmetrics,
48 /*fnmetrics*/ fnmetrics,
55 static char * dupcnstring( unsigned char *s, int len);
57 static FT_Library library;
60 static int enc_type, enc_found;
62 /* SFNT functions do not seem to be included by default in FT2beta8 */
66 * Open font and prepare to return information to the main driver.
67 * May print error and warning messages.
74 char *arg /* unused now */
79 if( FT_Init_FreeType( &library ) ) {
80 fprintf(stderr, "** FreeType initialization failed\n");
84 if( error = FT_New_Face( library, fname, 0, &face ) ) {
85 if ( error == FT_Err_Unknown_File_Format )
86 fprintf(stderr, "**** %s has format unknown to FreeType\n", fname);
88 fprintf(stderr, "**** Cannot access %s ****\n", fname);
92 if(FT_HAS_FIXED_SIZES(face)) {
93 WARNING_1 fprintf(stderr, "Font contains bitmaps\n");
95 if(FT_HAS_MULTIPLE_MASTERS(face)) {
96 WARNING_1 fprintf(stderr, "Font contains multiple masters, using default\n");
99 if(ISDBG(FT)) fprintf(stderr," %d units per EM\n", face->units_per_EM);
114 if( FT_Done_Face(face) ) {
115 WARNING_1 fprintf(stderr, "Errors when closing the font file, ignored\n");
117 if( FT_Done_FreeType(library) ) {
118 WARNING_1 fprintf(stderr, "Errors when stopping FreeType, ignored\n");
123 * Get the number of glyphs in font.
131 if(ISDBG(FT)) fprintf(stderr, "%d glyphs in font\n", face->num_glyphs);
132 return (int)face->num_glyphs;
136 * Get the names of the glyphs.
137 * Returns 0 if the names were assigned, non-zero if the font
138 * provides no glyph names.
146 #define MAX_NAMELEN 1024
147 unsigned char bf[1024];
150 if( ! FT_HAS_GLYPH_NAMES(face) ) {
151 WARNING_1 fprintf(stderr, "Font has no glyph names\n");
155 for(i=0; i < face->num_glyphs; i++) {
156 if( FT_Get_Glyph_Name(face, i, bf, MAX_NAMELEN) || bf[0]==0 ) {
157 sprintf(bf, "_g_%d", i);
158 WARNING_2 fprintf(stderr,
159 "Glyph No. %d has no postscript name, becomes %s\n", i, bf);
161 glyph_list[i].name = strdup(bf);
162 if(ISDBG(FT)) fprintf(stderr, "%d has name %s\n", i, bf);
163 if (glyph_list[i].name == NULL) {
164 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
172 * Get the metrics of the glyphs.
182 FT_Glyph_Metrics *met;
186 for(i=0; i < face->num_glyphs; i++) {
187 g = &(glyph_list[i]);
189 if( FT_Load_Glyph(face, i, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE) ) {
190 fprintf(stderr, "Can't load glyph %s, skipped\n", g->name);
194 met = &face->glyph->metrics;
196 if(FT_HAS_HORIZONTAL(face)) {
197 g->width = met->horiAdvance;
198 g->lsb = met->horiBearingX;
200 WARNING_2 fprintf(stderr, "Glyph %s has no horizontal metrics, guessed them\n", g->name);
201 g->width = met->width;
205 if( FT_Get_Glyph(face->glyph, &gly) ) {
206 fprintf(stderr, "Can't access glyph %s bbox, skipped\n", g->name);
210 FT_Glyph_Get_CBox(gly, ft_glyph_bbox_unscaled, &bbox);
216 g->ttf_pathlen = face->glyph->outline.n_points;
221 * Get the original encoding of the font.
222 * Returns 1 for if the original encoding is Unicode, 2 if the
223 * original encoding is other 16-bit, 0 if 8-bit.
237 for(e=0; e < face->num_charmaps; e++) {
238 fprintf(stderr, "found encoding pid=%d eid=%d\n",
239 face->charmaps[e]->platform_id,
240 face->charmaps[e]->encoding_id);
248 /* first check for an explicit PID/EID */
250 if(force_pid != -1) {
251 for(e=0; e < face->num_charmaps; e++) {
252 if(face->charmaps[e]->platform_id == force_pid
253 && face->charmaps[e]->encoding_id == force_eid) {
254 WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n",
255 force_pid, force_eid);
256 if( FT_Set_Charmap(face, face->charmaps[e]) ) {
257 fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
264 fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n",
265 force_pid, force_eid);
269 /* next check for a direct Adobe mapping */
272 for(e=0; e < face->num_charmaps; e++) {
273 if(face->charmaps[e]->encoding == ft_encoding_adobe_custom) {
274 WARNING_1 fputs("Found Adobe Custom Encoding\n", stderr);
275 if( FT_Set_Charmap(face, face->charmaps[e]) ) {
276 fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
284 for(e=0; e < face->num_charmaps; e++) {
285 if(face->charmaps[e]->platform_id == 3) {
286 switch(face->charmaps[e]->encoding_id) {
288 WARNING_1 fputs("Found Symbol Encoding\n", stderr);
291 WARNING_1 fputs("Found Unicode Encoding\n", stderr);
297 "****MS Encoding ID %d not supported****\n",
298 face->charmaps[e]->encoding_id);
299 fputs("Treating it like Symbol encoding\n", stderr);
306 if(e >= face->num_charmaps) {
307 WARNING_1 fputs("No Microsoft encoding, using first encoding available\n", stderr);
311 if( !face->charmaps || FT_Set_Charmap(face, face->charmaps[e]) ) {
312 fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
317 for(i=0; i<ENCTABSZ; i++) {
318 if(encoding[i] != -1)
320 if(enc_type == 1 || forcemap) {
322 if(code == (unsigned) -1)
327 code = FT_Get_Char_Index(face, code);
328 if(0 && ISDBG(FT)) fprintf(stderr, "code of %3d is %3d\n", i, code);
330 continue; /* .notdef */
337 /* duplicate a string with counter to a 0-terminated string */
348 if(( res = malloc(len+1) )==NULL) {
349 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
354 for(i=0; i<len; i++) {
355 if(( c=s[i] )>=' ' && c!=127)
359 WARNING_1 fprintf(stderr, "Some font name strings are in Unicode, may not show properly\n");
367 * Get the font metrics
371 struct font_metrics *fm
375 static char *fieldstocheck[3];
378 #endif /* ENABLE_SFNT */
381 fm->italic_angle = 0.0; /* FreeType hides the angle */
382 fm->underline_position = face->underline_position;
383 fm->underline_thickness = face->underline_thickness;
384 fm->is_fixed_pitch = FT_IS_FIXED_WIDTH(face);
386 fm->ascender = face->ascender;
387 fm->descender = face->descender;
389 fm->units_per_em = face->units_per_EM;
391 fm->bbox[0] = face->bbox.xMin;
392 fm->bbox[1] = face->bbox.yMin;
393 fm->bbox[2] = face->bbox.xMax;
394 fm->bbox[3] = face->bbox.yMax;
397 if( FT_Get_Sfnt_Name(face, TT_NAME_ID_COPYRIGHT, &sn) )
398 #endif /* ENABLE_SFNT */
399 fm->name_copyright = "";
402 fm->name_copyright = dupcnstring(sn.string, sn.string_len);
403 #endif /* ENABLE_SFNT */
405 fm->name_family = face->family_name;
407 fm->name_style = face->style_name;
408 if(fm->name_style == NULL)
412 if( FT_Get_Sfnt_Name(face, TT_NAME_ID_FULL_NAME, &sn) )
413 #endif /* ENABLE_SFNT */
418 fm->name_family = "";
421 len = strlen(fm->name_family) + strlen(fm->name_style) + 2;
422 if(( fm->name_full = malloc(len) )==NULL) {
423 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
426 strcpy(fm->name_full, fm->name_family);
427 if(strlen(fm->name_style) != 0) {
428 strcat(fm->name_full, " ");
429 strcat(fm->name_full, fm->name_style);
434 fm->name_full = dupcnstring(sn.string, sn.string_len);
435 #endif /* ENABLE_SFNT */
438 if( FT_Get_Sfnt_Name(face, TT_NAME_ID_VERSION_STRING, &sn) )
439 #endif /* ENABLE_SFNT */
440 fm->name_version = "1.0";
443 fm->name_version = dupcnstring(sn.string, sn.string_len);
444 #endif /* ENABLE_SFNT */
447 if( FT_Get_Sfnt_Name(face, TT_NAME_ID_PS_NAME , &sn) ) {
448 #endif /* ENABLE_SFNT */
449 if(( fm->name_ps = strdup(fm->name_full) )==NULL) {
450 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
455 fm->name_ps = dupcnstring(sn.string, sn.string_len);
456 #endif /* ENABLE_SFNT */
457 for(i=0; fm->name_ps[i]!=0; i++)
458 if(fm->name_ps[i] == ' ')
459 fm->name_ps[i] = '_'; /* no spaces in the Postscript name */
461 /* guess the boldness from the font names */
464 fieldstocheck[0] = fm->name_style;
465 fieldstocheck[1] = fm->name_full;
466 fieldstocheck[2] = fm->name_ps;
468 for(i=0; !fm->force_bold && i<sizeof fieldstocheck /sizeof(fieldstocheck[0]); i++) {
470 str=fieldstocheck[i];
471 for(j=0; str[j]!=0; j++) {
474 && ( j==0 || !isalpha(str[j-1]) )
476 && !strncmp("old",&str[j+1],3)
477 && !islower(str[j+4])
487 * Functions to decompose the outlines
491 static double lastx, lasty;
501 tox = fscale((double)to->x); toy = fscale((double)to->y);
503 /* FreeType does not do explicit closepath() */
504 if(curg->lastentry) {
507 fg_rmoveto(curg, tox, toy);
508 lastx = tox; lasty = toy;
521 tox = fscale((double)to->x); toy = fscale((double)to->y);
523 fg_rlineto(curg, tox, toy);
524 lastx = tox; lasty = toy;
536 double c1x, c1y, tox, toy;
538 c1x = fscale((double)control1->x); c1y = fscale((double)control1->y);
539 tox = fscale((double)to->x); toy = fscale((double)to->y);
542 (lastx + 2.0 * c1x) / 3.0, (lasty + 2.0 * c1y) / 3.0,
543 (2.0 * c1x + tox) / 3.0, (2.0 * c1y + toy) / 3.0,
545 lastx = tox; lasty = toy;
558 double c1x, c1y, c2x, c2y, tox, toy;
560 c1x = fscale((double)control1->x); c1y = fscale((double)control1->y);
561 c2x = fscale((double)control2->x); c2y = fscale((double)control2->y);
562 tox = fscale((double)to->x); toy = fscale((double)to->y);
564 fg_rrcurveto(curg, c1x, c1y, c2x, c2y, tox, toy);
565 lastx = tox; lasty = toy;
570 static FT_Outline_Funcs ft_outl_funcs = {
580 * Get the path of contrours for a glyph.
591 curg = &glyf_list[glyphno];
593 if( FT_Load_Glyph(face, glyphno, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE|FT_LOAD_NO_HINTING)
594 || face->glyph->format != ft_glyph_format_outline ) {
595 fprintf(stderr, "Can't load glyph %s, skipped\n", curg->name);
599 ol = &face->glyph->outline;
600 lastx = 0.0; lasty = 0.0;
602 if( FT_Outline_Decompose(ol, &ft_outl_funcs, NULL) ) {
603 fprintf(stderr, "Can't decompose outline of glyph %s, skipped\n", curg->name);
607 /* FreeType does not do explicit closepath() */
608 if(curg->lastentry) {
612 if(ol->flags & ft_outline_reverse_fill) {
613 assertpath(curg->entries, __FILE__, __LINE__, curg->name);
619 * Get the kerning data.
628 int nglyphs = face->num_glyphs;
632 if( nglyphs == 0 || !FT_HAS_KERNING(face) ) {
633 WARNING_1 fputs("No Kerning data\n", stderr);
637 for(i=0; i<nglyphs; i++) {
638 if( (glyph_list[i].flags & GF_USED) ==0)
640 for(j=0; j<nglyphs; j++) {
641 if( (glyph_list[j].flags & GF_USED) ==0)
643 if( FT_Get_Kerning(face, i, j, ft_kerning_unscaled, &k) )
648 addkernpair(i, j, k.x);