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/ftnames.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( 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, "_%d", i);
157 WARNING_2 fprintf(stderr,
158 "**** Glyph No. %d has no postscript name, becomes %s ****\n",
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( FT_Set_Charmap(face, face->charmaps[e]) ) {
312 fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
318 for(i=0; i<ENCTABSZ; i++) {
319 if(encoding[i] != -1)
321 if(enc_type == 1 || forcemap) {
323 if(code == (unsigned) -1)
328 code = FT_Get_Char_Index(face, code);
329 if(0 && ISDBG(FT)) fprintf(stderr, "code of %3d is %3d\n", i, code);
331 continue; /* .notdef */
338 /* duplicate a string with counter to a 0-terminated string */
347 if(( res = malloc(len+1) )==NULL) {
348 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
358 * Get the font metrics
362 struct font_metrics *fm
366 static char *fieldstocheck[3];
369 #endif /* ENABLE_SFNT */
372 fm->italic_angle = 0.0; /* FreeType hides the angle */
373 fm->underline_position = face->underline_position;
374 fm->underline_thickness = face->underline_thickness;
375 fm->is_fixed_pitch = FT_IS_FIXED_WIDTH(face);
377 fm->ascender = face->ascender;
378 fm->descender = face->descender;
380 fm->units_per_em = face->units_per_EM;
382 fm->bbox[0] = face->bbox.xMin;
383 fm->bbox[1] = face->bbox.yMin;
384 fm->bbox[2] = face->bbox.xMax;
385 fm->bbox[3] = face->bbox.yMax;
388 if( FT_Get_Sfnt_Name(face, TT_NAME_ID_COPYRIGHT, &sn) )
389 #endif /* ENABLE_SFNT */
390 fm->name_copyright = "";
393 fm->name_copyright = dupcnstring(sn.string, sn.string_len);
394 #endif /* ENABLE_SFNT */
396 fm->name_family = face->family_name;
398 fm->name_style = face->style_name;
399 if(fm->name_style == NULL)
403 if( FT_Get_Sfnt_Name(face, TT_NAME_ID_FULL_NAME, &sn) )
404 #endif /* ENABLE_SFNT */
408 len = strlen(fm->name_family) + strlen(fm->name_style) + 2;
409 if(( fm->name_full = malloc(len) )==NULL) {
410 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
413 strcpy(fm->name_full, fm->name_family);
414 if(strlen(fm->name_style) != 0) {
415 strcat(fm->name_full, " ");
416 strcat(fm->name_full, fm->name_style);
421 fm->name_full = dupcnstring(sn.string, sn.string_len);
422 #endif /* ENABLE_SFNT */
425 if( FT_Get_Sfnt_Name(face, TT_NAME_ID_VERSION_STRING, &sn) )
426 #endif /* ENABLE_SFNT */
427 fm->name_version = "1.0";
430 fm->name_version = dupcnstring(sn.string, sn.string_len);
431 #endif /* ENABLE_SFNT */
434 if( FT_Get_Sfnt_Name(face, TT_NAME_ID_PS_NAME , &sn) ) {
435 #endif /* ENABLE_SFNT */
436 if(( fm->name_ps = strdup(fm->name_full) )==NULL) {
437 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
442 fm->name_ps = dupcnstring(sn.string, sn.string_len);
443 #endif /* ENABLE_SFNT */
445 /* guess the boldness from the font names */
448 fieldstocheck[0] = fm->name_style;
449 fieldstocheck[1] = fm->name_full;
450 fieldstocheck[2] = fm->name_ps;
452 for(i=0; !fm->force_bold && i<sizeof fieldstocheck /sizeof(fieldstocheck[0]); i++) {
453 str=fieldstocheck[i];
454 for(i=0; str[i]!=0; i++) {
457 && ( i==0 || !isalpha(str[i-1]) )
459 && !strncmp("old",&str[i+1],3)
460 && !islower(str[i+4])
470 * Functions to decompose the outlines
474 static double lastx, lasty;
484 tox = fscale((double)to->x); toy = fscale((double)to->y);
486 /* FreeType does not do explicit closepath() */
487 if(curg->lastentry) {
490 fg_rmoveto(curg, tox, toy);
491 lastx = tox; lasty = toy;
504 tox = fscale((double)to->x); toy = fscale((double)to->y);
506 fg_rlineto(curg, tox, toy);
507 lastx = tox; lasty = toy;
519 double c1x, c1y, tox, toy;
521 c1x = fscale((double)control1->x); c1y = fscale((double)control1->y);
522 tox = fscale((double)to->x); toy = fscale((double)to->y);
525 (lastx + 2.0 * c1x) / 3.0, (lasty + 2.0 * c1y) / 3.0,
526 (2.0 * c1x + tox) / 3.0, (2.0 * c1y + toy) / 3.0,
528 lastx = tox; lasty = toy;
541 double c1x, c1y, c2x, c2y, tox, toy;
543 c1x = fscale((double)control1->x); c1y = fscale((double)control1->y);
544 c2x = fscale((double)control2->x); c2y = fscale((double)control2->y);
545 tox = fscale((double)to->x); toy = fscale((double)to->y);
547 fg_rrcurveto(curg, c1x, c1y, c2x, c2y, tox, toy);
548 lastx = tox; lasty = toy;
553 static FT_Outline_Funcs ft_outl_funcs = {
563 * Get the path of contrours for a glyph.
574 curg = &glyf_list[glyphno];
576 if( FT_Load_Glyph(face, glyphno, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE|FT_LOAD_NO_HINTING)
577 || face->glyph->format != ft_glyph_format_outline ) {
578 fprintf(stderr, "Can't load glyph %s, skipped\n", curg->name);
582 ol = &face->glyph->outline;
583 lastx = 0.0; lasty = 0.0;
585 if( FT_Outline_Decompose(ol, &ft_outl_funcs, NULL) ) {
586 fprintf(stderr, "Can't decompose outline of glyph %s, skipped\n", curg->name);
590 /* FreeType does not do explicit closepath() */
591 if(curg->lastentry) {
595 if(ol->flags & ft_outline_reverse_fill) {
596 assertpath(curg->entries, __FILE__, __LINE__, curg->name);
602 * Get the kerning data.
611 int nglyphs = face->num_glyphs;
615 if( nglyphs == 0 || !FT_HAS_KERNING(face) ) {
616 WARNING_1 fputs("No Kerning data\n", stderr);
620 for(i=0; i<nglyphs; i++) {
621 if( (glyph_list[i].flags & GF_USED) ==0)
623 for(j=0; j<nglyphs; j++) {
624 if( (glyph_list[j].flags & GF_USED) ==0)
626 if( FT_Get_Kerning(face, i, j, ft_kerning_unscaled, &k) )
631 addkernpair(i, j, k.x);