Logo Search packages:      
Sourcecode: bg5ps version File versions

ttf2psm.c

/*              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<stdio.h>
#include<freetype/freetype.h>
#include<string.h>
#include<ctype.h>

#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] <ttc/ttf font file>\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 );
}


Generated by  Doxygen 1.6.0   Back to index