/* ttf2psm.c * Rewrite by Chingson Chen * chingson@ms4.hinet.net * * $Log: ttf2psm.c,v $ * Revision 1.4 2000/02/14 19:59:23 platin * Adjust 'testchar' in ttf2psm. * * Revision 1.3 2000/02/14 18:51:45 platin * Show TargetEncoding and TargetEncodingID in output. * * Revision 1.2 2000/02/14 18:16:53 platin * * Modify ttf2psm.c and add gb_in.c/gbtou8.c to make * ttf2psm support multibyte char rendering. At this time, * GB and BIG5 aupport were added. * * */ #include #include #include #include #include"utf.h" #define RESOLUTION 1200 #define CHARSIZE 120 // By JYJ #define BIG5_ENCODING 1 #define GB_ENCODING 2 void draw_outline( FILE *, TT_Outline *, unsigned int, unsigned int); void draw_curve( FILE *, TT_Vector *, TT_Vector *, TT_Vector *); TT_Error error; TT_F26Dot6 width=300; main( int argc, char **argv) { TT_Face MyFace; TT_Engine MyEngine; TT_Face_Properties MyProperties; TT_Instance MyInstance; TT_Glyph MyGlyph; TT_Outline MyOutline; TT_CharMap UnicodeCharMap; TT_CharMap MBCharMap[3]; // many charmaps of big5 TT_UShort mb_map_number=0; TT_UShort MyPlatformID, MyEncodingID; TT_UShort Unicode_CharMap_ID = (TT_UShort)100; // short unicode charmap TT_UShort MB_CharMap_ID = (TT_UShort)100; // short unicode charmap TT_UShort TargetEncoding, TargetEncodingID; unsigned int testchar; FILE *filenull; char *fontfile; unsigned int i; int j,k; int charmap_count; filenull = fopen( "/dev/null", "w"); if( argc < 3 ) { fprintf( stderr, "%s -[bg] \n", argv[0]); return(-1); } // Only Big5 and GB are supported at this time. switch (argv[1][1]) { case 'b': TargetEncoding = BIG5_ENCODING; TargetEncodingID = TT_MS_ID_BIG_5; testchar = 0xa440; break; case 'g': TargetEncoding = GB_ENCODING; TargetEncodingID = TT_MS_ID_GB2312; testchar = 0xd2bb; break; default: TargetEncoding = BIG5_ENCODING; TargetEncodingID = TT_MS_ID_BIG_5; testchar = 0xa440; break; } if( error = TT_Init_FreeType( &MyEngine ) ) { fprintf(stderr, "init freetype engine failure.\n Reason:%s\n", TT_ErrToString18( error) ); return(1); } // Open tt[fc] font... fontfile=argv[2]; i = strlen( fontfile ); if( tolower(fontfile[i-1]) == 'f' ) { if ( error = TT_Open_Face(MyEngine,fontfile,&MyFace ) ) { fprintf(stderr, "init Face failure.\n Reason:%s\n", TT_ErrToString18( error) ); return(-2); } } else { if( error = TT_Open_Collection( MyEngine,fontfile,(TT_ULong) 1,&MyFace ) ) { fprintf(stderr, "init face failure.\n Reason:%s\n", TT_ErrToString18( error) ); return(2); } } if ( error = TT_Get_Face_Properties( MyFace, &MyProperties ) ) { fprintf(stderr, "Get Properties failure.\n Reason:%s\n", TT_ErrToString18( error) ); return(3); } printf("%%%% file: %s\n%%%%num glyph:%d\n%%%%Max Points: %d\n", fontfile, MyProperties.num_Glyphs, MyProperties.max_Points ); printf("%%%%\n%%%% TargetEncoding: %d\n%%%% TargetEncodingID: %d\n", TargetEncoding,TargetEncodingID); printf("%%%%\n%%%%Max Contours:%d\n%%%%Num Faces:%d\n", MyProperties.max_Contours, MyProperties.num_Faces ); error = TT_New_Instance( MyFace, &MyInstance); if( error ){ fprintf( stderr, "new instance error: %s\n", TT_ErrToString18(error)); return(-2); } error = TT_Set_Instance_Resolutions( MyInstance, (TT_UShort) RESOLUTION, (TT_UShort) RESOLUTION ); if( error ){ fprintf( stderr, "set resolution error: %s\n", TT_ErrToString18(error)); return(-3); } error = TT_Set_Instance_CharSizes( MyInstance, (TT_F26Dot6)(CHARSIZE << 6) , (TT_F26Dot6)(CHARSIZE << 6)); if( error ){ fprintf( stderr, "set charsize error: %s\n", TT_ErrToString18(error)); return(-4); } error = TT_New_Glyph( MyFace,&MyGlyph ); if( error ){ fprintf( stderr, "new glyph error: %s\n", TT_ErrToString18(error)); return(-2); } charmap_count = MyProperties.num_CharMaps; printf("%%%%charmap count : %d\n", charmap_count ); for( i = 0; i < charmap_count; i++) { TT_Get_CharMap_ID( MyFace,(TT_UShort) i,&MyPlatformID,&MyEncodingID ); printf( "%%%%CharMap Index %d: Plateform:%d Encoding: %d\n", i, MyPlatformID, MyEncodingID); if( MyPlatformID == 3 /* MS win */ && MyEncodingID == 1 ) /* Unicode */ { Unicode_CharMap_ID = i; error = TT_Get_CharMap( MyFace, i,&UnicodeCharMap ); if(error) { fprintf(stderr, "get charmap error:%s", TT_ErrToString18(error)); return(-4); } break; } if( MyPlatformID == 3 /* MS win */ && MyEncodingID == TargetEncodingID ) /* Got the map for TargetEncoding ? */ { MB_CharMap_ID = i; error = TT_Get_CharMap( MyFace, i,&(MBCharMap [mb_map_number++]) ); if(error) { fprintf(stderr, "get charmap error:%s", TT_ErrToString18(error)); return(-4); } break; } } if( MB_CharMap_ID==(TT_UShort)(100) && Unicode_CharMap_ID ==(TT_UShort)(100) ) { fprintf( stderr, "No UNICODE or proper Multibyte CharMap!\n"); return(-3); } printf("%%%% End of font file description\n"); i = testchar; while( i != -1 ) { if( MB_CharMap_ID < (TT_UShort)(100) ) { for( j = 0; j < mb_map_number; j++) if( (k=TT_Char_Index(MBCharMap[j], (TT_UShort)i )) > 0 ) break; error = TT_Load_Glyph(MyInstance,MyGlyph,k,TTLOAD_DEFAULT ); } else { long utfcode; switch (TargetEncoding) { case BIG5_ENCODING: utfcode=b5tou8(i); break; case GB_ENCODING: utfcode=gbtou8(i); break; default: fprintf( stderr, "Noway for this to happen!\n"); return(-4); break; } error = TT_Load_Glyph(MyInstance,MyGlyph, TT_Char_Index( UnicodeCharMap,(TT_UShort) utfcode), TTLOAD_DEFAULT ); } if( error ) { fprintf( stderr, "Load Glyph Error: %s",TT_ErrToString18(error)); return(-5); } error = TT_Get_Glyph_Outline( MyGlyph, &MyOutline); if( error ) { fprintf( stderr, "Load Outline Error: %s",TT_ErrToString18(error)); return(-6); } TT_Translate_Outline( &MyOutline, 0, ((CHARSIZE/2+10)<<6) ); draw_outline( filenull, &MyOutline, i, testchar ); scanf( "%d", &i); filenull = stdout; } return(0); } void draw_outline( FILE *out, TT_Outline *theoutline, unsigned int i, unsigned int testchar) { TT_BBox my_bbox; int j,k,m,n; TT_Vector initial_point, contour_initial_point, tmp_point; int point_num; fprintf( out, "%%%%n_contours: %d, n_points: %d\n", theoutline->n_contours, theoutline->n_points ); error = TT_Get_Outline_BBox( theoutline, &my_bbox ); if( error ) { fprintf( stderr, "Get outline bbox error:%s\n", TT_ErrToString18( error) ); exit(1); } if( i == testchar ) width = my_bbox.xMax-my_bbox.xMin; fprintf( out, "/w%d\n{\n gsave\n 12 %d div 12 %d div scale\n", i, (int)(width*22/20), (int)(width*22/20) ); fprintf( out, "{ ucache %d %d %d %d setbbox\n", my_bbox.xMin, my_bbox.yMin, my_bbox.xMax, my_bbox.yMax ); for( j = 0, k = 0 ; j < theoutline->n_contours; j++) { /* first point of a contour */ if( k == theoutline->contours[j] ) { k++; continue; // skip single point contour } if( ((theoutline->flags[k])&0x01) == 0 ) // off directly { m = theoutline->contours[j]; // first step is to define the contour_initial_point if( (theoutline->flags[m])&0x01) // final point on curve { contour_initial_point.x = theoutline->points[m].x; contour_initial_point.y = theoutline->points[m].y; } else { contour_initial_point.x = (theoutline->points[m].x + theoutline->points[k].x)/2; contour_initial_point.y = (theoutline->points[m].y + theoutline->points[k].y)/2; } // then the initial point of next segment if( (theoutline->flags[k+1])&0x01) // next point on curve { initial_point.x = theoutline->points[k+1].x; initial_point.y = theoutline->points[k+1].y; } else { initial_point.x = (theoutline->points[k].x + theoutline->points[k+1].x)/2; initial_point.y = (theoutline->points[k].y + theoutline->points[k+1].y)/2; } fprintf( out, "%d %d moveto\n", contour_initial_point.x, contour_initial_point.y ); draw_curve( out, &contour_initial_point, &(theoutline->points[k]), &initial_point ); if( (theoutline->flags[k+1])&0x01) k++; } else{ initial_point.x = theoutline->points[k].x; initial_point.y = theoutline->points[k].y; contour_initial_point.x = initial_point.x; contour_initial_point.y = initial_point.y; fprintf( out, "%d %d moveto\n", theoutline->points[k].x, theoutline->points[k].y ); } while( k < theoutline->contours[j] ) // each segment/curve { if( (theoutline->flags[k+1])&0x01 ) // on_curve { fprintf(out, "%d %d lineto\n", theoutline->points[k+1].x, theoutline->points[k+1].y); initial_point.x = theoutline->points[k+1].x; initial_point.y = theoutline->points[k+1].y; k ++; continue; } if( k == theoutline->contours[j] -1 ) // last point off curve { draw_curve( out, &initial_point, &(theoutline->points[k+1]) , &contour_initial_point ); k++; break; } if( (theoutline->flags[k+2])&0x01 ) // one off in two on { draw_curve( out, &initial_point, &(theoutline->points[k+1]), &(theoutline->points[k+2]) ); initial_point.x = theoutline->points[k+2].x; initial_point.y = theoutline->points[k+2].y; k+=2; continue; } if( ((theoutline->flags[k+2])&0x01) == 0 ) // 2 consecutive off { tmp_point.x = (theoutline->points[k+1].x + theoutline->points[k+2].x)/2 ; tmp_point.y = (theoutline->points[k+1].y + theoutline->points[k+2].y)/2 ; draw_curve( out, &initial_point, &(theoutline->points[k+1]), &tmp_point ); initial_point.x = tmp_point.x; initial_point.y = tmp_point.y; k ++; continue; } } fprintf( out, "%d %d lineto\n", contour_initial_point.x, contour_initial_point.y ); k = theoutline->contours[j]+1; // next contour } fprintf(out," closepath } \nufill \n"); fprintf(out,"grestore } bind def\n" ); } void draw_curve( FILE *out, TT_Vector *p0, TT_Vector *p1, TT_Vector *p2) { fprintf( out, "%d %d %d %d %d %d curveto\n", p0->x + (p1->x - p0->x)*2/3, p0->y + (p1->y - p0->y)*2/3, p1->x + (p2->x - p1->x)/3, p1->y + (p2->y - p1->y)/3, p2->x, p2->y ); }