2 * The font parser using the FreeType library version 2.
14 #include <sys/types.h>
15 #include <freetype/freetype.h>
16 #include <freetype/ftglyph.h>
17 #include <freetype/ftsnames.h>
18 #include <freetype/ttnameid.h>
19 #include <freetype/ftoutln.h>
23 /* prototypes of call entries */
24 static void openfont(char *fname, char *arg);
25 static void closefont( void);
26 static int getnglyphs ( void);
27 static int glnames( GLYPH *glyph_list);
28 static void glmetrics( GLYPH *glyph_list);
29 static int glenc( GLYPH *glyph_list, int *encoding, int *unimap);
30 static void fnmetrics( struct font_metrics *fm);
31 static void glpath( int glyphno, GLYPH *glyph_list);
32 static void kerning( GLYPH *glyph_list);
36 /* front-end descriptor */
37 struct frontsw freetype_sw = {
39 /*descr*/ "based on the FreeType library",
40 /*suffix*/ { "ttf", "otf", "pfa", "pfb" },
43 /*nglyphs*/ getnglyphs,
45 /*glmetrics*/ glmetrics,
47 /*fnmetrics*/ fnmetrics,
54 static char * dupcnstring( unsigned char *s, int len);
56 static FT_Library library;
59 static int enc_type, enc_found;
61 /* SFNT functions do not seem to be included by default in FT2beta8 */
65 * Open font and prepare to return information to the main driver.
66 * May print error and warning messages.
73 char *arg /* unused now */
78 if( FT_Init_FreeType( &library ) ) {
79 fprintf(stderr, "** FreeType initialization failed\n");
83 if( error = FT_New_Face( library, fname, 0, &face ) ) {
84 if ( error == FT_Err_Unknown_File_Format )
85 fprintf(stderr, "**** %s has format unknown to FreeType\n", fname);
87 fprintf(stderr, "**** Cannot access %s ****\n", fname);
91 if(FT_HAS_FIXED_SIZES(face)) {
92 WARNING_1 fprintf(stderr, "Font contains bitmaps\n");
94 if(FT_HAS_MULTIPLE_MASTERS(face)) {
95 WARNING_1 fprintf(stderr, "Font contains multiple masters, using default\n");
98 if(ISDBG(FT)) fprintf(stderr," %d units per EM\n", face->units_per_EM);
113 if( FT_Done_Face(face) ) {
114 WARNING_1 fprintf(stderr, "Errors when closing the font file, ignored\n");
116 if( FT_Done_FreeType(library) ) {
117 WARNING_1 fprintf(stderr, "Errors when stopping FreeType, ignored\n");
122 * Get the number of glyphs in font.
130 if(ISDBG(FT)) fprintf(stderr, "%d glyphs in font\n", face->num_glyphs);
131 return (int)face->num_glyphs;
135 * Get the names of the glyphs.
136 * Returns 0 if the names were assigned, non-zero if the font
137 * provides no glyph names.
145 #define MAX_NAMELEN 1024
146 unsigned char bf[1024];
149 if( ! FT_HAS_GLYPH_NAMES(face) ) {
150 WARNING_1 fprintf(stderr, "Font has no glyph names\n");
154 for(i=0; i < face->num_glyphs; i++) {
155 if( FT_Get_Glyph_Name(face, i, bf, MAX_NAMELEN) || bf[0]==0 ) {
156 sprintf(bf, "_g_%d", i);
157 WARNING_2 fprintf(stderr,
158 "Glyph No. %d has no postscript name, becomes %s\n", i, bf);
160 glyph_list[i].name = strdup(bf);
161 if(ISDBG(FT)) fprintf(stderr, "%d has name %s\n", i, bf);
162 if (glyph_list[i].name == NULL) {
163 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
171 * Get the metrics of the glyphs.
181 FT_Glyph_Metrics *met;
185 for(i=0; i < face->num_glyphs; i++) {
186 g = &(glyph_list[i]);
188 if( FT_Load_Glyph(face, i, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE) ) {
189 fprintf(stderr, "Can't load glyph %s, skipped\n", g->name);
193 met = &face->glyph->metrics;
195 if(FT_HAS_HORIZONTAL(face)) {
196 g->width = met->horiAdvance;
197 g->lsb = met->horiBearingX;
199 WARNING_2 fprintf(stderr, "Glyph %s has no horizontal metrics, guessed them\n", g->name);
200 g->width = met->width;
204 if( FT_Get_Glyph(face->glyph, &gly) ) {
205 fprintf(stderr, "Can't access glyph %s bbox, skipped\n", g->name);
209 FT_Glyph_Get_CBox(gly, ft_glyph_bbox_unscaled, &bbox);
215 g->ttf_pathlen = face->glyph->outline.n_points;
220 * Get the original encoding of the font.
221 * Returns 1 for if the original encoding is Unicode, 2 if the
222 * original encoding is other 16-bit, 0 if 8-bit.
236 for(e=0; e < face->num_charmaps; e++) {
237 fprintf(stderr, "found encoding pid=%d eid=%d\n",
238 face->charmaps[e]->platform_id,
239 face->charmaps[e]->encoding_id);
247 /* first check for an explicit PID/EID */
249 if(force_pid != -1) {
250 for(e=0; e < face->num_charmaps; e++) {
251 if(face->charmaps[e]->platform_id == force_pid
252 && face->charmaps[e]->encoding_id == force_eid) {
253 WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n",
254 force_pid, force_eid);
255 if( FT_Set_Charmap(face, face->charmaps[e]) ) {
256 fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
263 fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n",
264 force_pid, force_eid);
268 /* next check for a direct Adobe mapping */
271 for(e=0; e < face->num_charmaps; e++) {
272 if(face->charmaps[e]->encoding == ft_encoding_adobe_custom) {
273 WARNING_1 fputs("Found Adobe Custom Encoding\n", stderr);
274 if( FT_Set_Charmap(face, face->charmaps[e]) ) {
275 fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
283 for(e=0; e < face->num_charmaps; e++) {
284 if(face->charmaps[e]->platform_id == 3) {
285 switch(face->charmaps[e]->encoding_id) {
287 WARNING_1 fputs("Found Symbol Encoding\n", stderr);
290 WARNING_1 fputs("Found Unicode Encoding\n", stderr);
296 "****MS Encoding ID %d not supported****\n",
297 face->charmaps[e]->encoding_id);
298 fputs("Treating it like Symbol encoding\n", stderr);
305 if(e >= face->num_charmaps) {
306 WARNING_1 fputs("No Microsoft encoding, using first encoding available\n", stderr);
310 if( FT_Set_Charmap(face, face->charmaps[e]) ) {
311 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 */
417 len = strlen(fm->name_family) + strlen(fm->name_style) + 2;
418 if(( fm->name_full = malloc(len) )==NULL) {
419 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
422 strcpy(fm->name_full, fm->name_family);
423 if(strlen(fm->name_style) != 0) {
424 strcat(fm->name_full, " ");
425 strcat(fm->name_full, fm->name_style);
430 fm->name_full = dupcnstring(sn.string, sn.string_len);
431 #endif /* ENABLE_SFNT */
434 if( FT_Get_Sfnt_Name(face, TT_NAME_ID_VERSION_STRING, &sn) )
435 #endif /* ENABLE_SFNT */
436 fm->name_version = "1.0";
439 fm->name_version = dupcnstring(sn.string, sn.string_len);
440 #endif /* ENABLE_SFNT */
443 if( FT_Get_Sfnt_Name(face, TT_NAME_ID_PS_NAME , &sn) ) {
444 #endif /* ENABLE_SFNT */
445 if(( fm->name_ps = strdup(fm->name_full) )==NULL) {
446 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
451 fm->name_ps = dupcnstring(sn.string, sn.string_len);
452 #endif /* ENABLE_SFNT */
453 for(i=0; fm->name_ps[i]!=0; i++)
454 if(fm->name_ps[i] == ' ')
455 fm->name_ps[i] = '_'; /* no spaces in the Postscript name *m
457 /* guess the boldness from the font names */
460 fieldstocheck[0] = fm->name_style;
461 fieldstocheck[1] = fm->name_full;
462 fieldstocheck[2] = fm->name_ps;
464 for(i=0; !fm->force_bold && i<sizeof fieldstocheck /sizeof(fieldstocheck[0]); i++) {
465 str=fieldstocheck[i];
466 for(i=0; str[i]!=0; i++) {
469 && ( i==0 || !isalpha(str[i-1]) )
471 && !strncmp("old",&str[i+1],3)
472 && !islower(str[i+4])
482 * Functions to decompose the outlines
486 static double lastx, lasty;
496 tox = fscale((double)to->x); toy = fscale((double)to->y);
498 /* FreeType does not do explicit closepath() */
499 if(curg->lastentry) {
502 fg_rmoveto(curg, tox, toy);
503 lastx = tox; lasty = toy;
516 tox = fscale((double)to->x); toy = fscale((double)to->y);
518 fg_rlineto(curg, tox, toy);
519 lastx = tox; lasty = toy;
531 double c1x, c1y, tox, toy;
533 c1x = fscale((double)control1->x); c1y = fscale((double)control1->y);
534 tox = fscale((double)to->x); toy = fscale((double)to->y);
537 (lastx + 2.0 * c1x) / 3.0, (lasty + 2.0 * c1y) / 3.0,
538 (2.0 * c1x + tox) / 3.0, (2.0 * c1y + toy) / 3.0,
540 lastx = tox; lasty = toy;
553 double c1x, c1y, c2x, c2y, tox, toy;
555 c1x = fscale((double)control1->x); c1y = fscale((double)control1->y);
556 c2x = fscale((double)control2->x); c2y = fscale((double)control2->y);
557 tox = fscale((double)to->x); toy = fscale((double)to->y);
559 fg_rrcurveto(curg, c1x, c1y, c2x, c2y, tox, toy);
560 lastx = tox; lasty = toy;
565 static FT_Outline_Funcs ft_outl_funcs = {
575 * Get the path of contrours for a glyph.
586 curg = &glyf_list[glyphno];
588 if( FT_Load_Glyph(face, glyphno, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE|FT_LOAD_NO_HINTING)
589 || face->glyph->format != ft_glyph_format_outline ) {
590 fprintf(stderr, "Can't load glyph %s, skipped\n", curg->name);
594 ol = &face->glyph->outline;
595 lastx = 0.0; lasty = 0.0;
597 if( FT_Outline_Decompose(ol, &ft_outl_funcs, NULL) ) {
598 fprintf(stderr, "Can't decompose outline of glyph %s, skipped\n", curg->name);
602 /* FreeType does not do explicit closepath() */
603 if(curg->lastentry) {
607 if(ol->flags & ft_outline_reverse_fill) {
608 assertpath(curg->entries, __FILE__, __LINE__, curg->name);
614 * Get the kerning data.
623 int nglyphs = face->num_glyphs;
627 if( nglyphs == 0 || !FT_HAS_KERNING(face) ) {
628 WARNING_1 fputs("No Kerning data\n", stderr);
632 for(i=0; i<nglyphs; i++) {
633 if( (glyph_list[i].flags & GF_USED) ==0)
635 for(j=0; j<nglyphs; j++) {
636 if( (glyph_list[j].flags & GF_USED) ==0)
638 if( FT_Get_Kerning(face, i, j, ft_kerning_unscaled, &k) )
643 addkernpair(i, j, k.x);