draw9.c

0000/******************************************
0001  FreeType
0002******************************************/
0003#include <stdlib.h>
0004#include <string.h>
0005#include "draw6.h"
0006#include "draw7.h"
0007#include "draw8.h"
0008#include <ft2build.h>
0009#include FT_FREETYPE_H
0010#include <freetype/freetype.h>
0011#include <freetype/ftglyph.h>
0012#include <stdio.h>
0013#include <iconv.h>
0014
0015#define MAX_GLYPHS 80
0016
0017typedef struct  TGlyph_
0018{
0019 FT_UInt    index;    /* glyph index                  */
0020 FT_Vector  pos;      /* glyph origin on the baseline */
0021 FT_Glyph   image;    /* glyph image                  */
0022} TGlyph, *PGlyph;
0023
0024FT_Library  library=0;   /* handle to library     */
0025FT_Face     face;      /* handle to face object */
0026FT_GlyphSlot  slot;  /* a small shortcut */
0027
0028double position=0,ang=0;
0029double angle;
0030int sjis;
0031
0032void euc2sjis(unsigned char *c1,unsigned char *c2)
0033{
0034 if((*c1%2)==0) *c2-=0x02;
0035 else{
0036  *c2-=0x61;
0037  if(*c2>0x7e) ++*c2;
0038 }
0039 if(*c1<0xdf){
0040  ++*c1;
0041  *c1/=2;
0042  *c1+=0x30;
0043 }
0044 else{
0045  ++*c1;
0046  *c1/=2;
0047  *c1+=0x70;
0048 }
0049}
0050
0051int FDrawStr(char *c)
0052{
0053 TGlyph glyphs[MAX_GLYPHS];  /* glyphs table           */
0054 PGlyph glyph;               /* current glyph in table */
0055 FT_UInt num_glyphs;
0056 FT_BBox bbox;
0057 int error;
0058 FT_Matrix matrix;              /* transformation matrix */
0059 FT_Vector pen;
0060 FT_UInt glyph_index;
0061 FT_Bool use_kerning;
0062 FT_UInt previous;
0063 int pen_x, pen_y, n;
0064 int num_chars;
0065 int i,j,k;
0066 int string_width,string_height;
0067 int start_x,start_y;
0068 int left,top,right,bottom,startx,starty,middlex,middley,endx,endy;
0069 int left1,top1,right1,bottom1,startx1,starty1,middlex1,middley1,endx1,endy1;
0070 double x,y,x1,y1;
0071 int wid,hei;
0072 PixMap *p;
0073 unsigned char *pc;
0074 FT_Vector  start;
0075 unsigned char c1,c2;
0076 char s[300];
0077 iconv_t cd;
0078 char *s2;
0079 char *s3;
0080
0081 /*** 0th phase : convert UTF-8 to EUC-JP ***/
0082 if(sjis){
0083   //  cd=iconv_open("EUC-JP","UTF-8");
0084  cd=iconv_open("UTF16BE","UTF-8");
0085  s2=c;
0086  s3=s;
0087  i=strlen(c);
0088  j=299;
0089  iconv(cd,&s2,&i,&s3,&j);
0090  iconv_close(cd);
0091  s[299-j]='\0';
0092 }
0093
0094 /*** 1st phase : get pixbuf size ***/
0095 pen_x=0;   /* start at (0,0)! */
0096 pen_y=0;
0097
0098 num_glyphs=0;
0099 use_kerning=FT_HAS_KERNING( face );
0100
0101 previous=0;
0102
0103 if(sjis){
0104  num_chars=strlen(s);
0105  num_chars/=2;
0106 }
0107 else num_chars=strlen(c);
0108
0109 glyph = glyphs;
0110 for(n=0;n<num_chars;n++){
0111  if(sjis){
0112   i=0;
0113   c1=*((unsigned char *)s+2*n);
0114   c2=*((unsigned char *)s+2*n+1);
0115   //   euc2sjis(&c1,&c2);
0116   *(unsigned char *)(&i)=c2;
0117   *((unsigned char *)(&i)+1)=c1;
0118  }
0119  else i=c[n];
0120  glyph->index=FT_Get_Char_Index(face,i);
0121
0122  if ( use_kerning && previous && glyph->index ){
0123   FT_Vector  delta;
0124   FT_Get_Kerning(face,previous, glyph->index,
0125                            ft_kerning_default,&delta);
0126   pen_x+=delta.x>>6;
0127  }
0128
0129  /* store current pen position */
0130  glyph->pos.x=pen_x*64;
0131  glyph->pos.y=pen_y*64;
0132
0133
0134  /* load glyph image into the slot.  DO NOT RENDER IT! */
0135  error=FT_Load_Glyph(face,glyph->index,FT_LOAD_DEFAULT);
0136  if(error) continue;  /* ignore errors, jump to next glyph */
0137
0138  /* extract glyph image and store it in our table */
0139  error=FT_Get_Glyph(face->glyph,&glyph->image);
0140  if(error) continue;  /* ignore errors, jump to next glyph */
0141
0142  /* translate the glyph image now */
0143  FT_Glyph_Transform(glyph->image,0,&glyph->pos);
0144
0145  pen_x+=slot->advance.x>>6;
0146  previous=glyph->index;
0147
0148  /* increment number of glyphs */
0149  glyph++;
0150 }
0151 /* count number of glyphs loaded */
0152 num_glyphs=glyph-glyphs;
0153
0154 /* initialize string bbox to "empty" values */
0155 bbox.xMin=bbox.yMin= 32000;
0156 bbox.xMax=bbox.yMax=-32000;
0157
0158 /* for each glyph image, compute its bounding box, */
0159
0160 for(n=0;n<num_glyphs;n++){
0161  FT_BBox  glyph_bbox;
0162  FT_Glyph_Get_CBox( glyphs[n].image,ft_glyph_bbox_pixels, &glyph_bbox );
0163  if(glyph_bbox.xMin<bbox.xMin)
0164   bbox.xMin=glyph_bbox.xMin;
0165  if(glyph_bbox.yMin<bbox.yMin)
0166   bbox.yMin=glyph_bbox.yMin;
0167  if(glyph_bbox.xMax>bbox.xMax)
0168   bbox.xMax=glyph_bbox.xMax;
0169  if(glyph_bbox.yMax>bbox.yMax)
0170   bbox.yMax=glyph_bbox.yMax;
0171 }
0172 /* check that we really grew the string bbox */
0173 if(bbox.xMin>bbox.xMax){
0174  bbox.xMin=0;
0175  bbox.yMin=0;
0176  bbox.xMax=0;
0177  bbox.yMax=0;
0178 }
0179
0180 /* compute string dimensions in integer pixels */
0181 left1=bottom1=32000;
0182 top1=right1=-32000;
0183 x=bbox.xMin;
0184 y=bbox.yMax;
0185 i=x*cos(angle)-y*sin(angle);
0186 j=x*sin(angle)+y*cos(angle);
0187 if(i<left1) left1=i;
0188 if(i>right1) right1=i;
0189 if(j<bottom1) bottom1=j;
0190 if(j>top1) top1=j;
0191 x=bbox.xMin;
0192 y=bbox.yMin;
0193 i=x*cos(angle)-y*sin(angle);
0194 j=x*sin(angle)+y*cos(angle);
0195 if(i<left1) left1=i;
0196 if(i>right1) right1=i;
0197 if(j<bottom1) bottom1=j;
0198 if(j>top1) top1=j;
0199 x=bbox.xMax;
0200 y=bbox.yMin;
0201 i=x*cos(angle)-y*sin(angle);
0202 j=x*sin(angle)+y*cos(angle);
0203 if(i<left1) left1=i;
0204 if(i>right1) right1=i;
0205 if(j<bottom1) bottom1=j;
0206 if(j>top1) top1=j;
0207 x=bbox.xMax;
0208 y=bbox.yMax;
0209 i=x*cos(angle)-y*sin(angle);
0210 j=x*sin(angle)+y*cos(angle);
0211 if(i<left1) left1=i;
0212 if(i>right1) right1=i;
0213 if(j<bottom1) bottom1=j;
0214 if(j>top1) top1=j;
0215
0216 wid=right1-left1+4;
0217 hei=top1-bottom1+4;
0218 startx=-left1+2; /* (0,0) transformed */
0219 starty=top1+2;
0220 x=bbox.xMax;
0221 y=0.;
0222 i=x*cos(angle)-y*sin(angle);
0223 j=x*sin(angle)+y*cos(angle);
0224 endx=i-left1+2;
0225 endy=top1-j+2;
0226
0227 p=pcreate(2,wid,hei); /* 8-bit grayscale */
0228 j=wid*hei;
0229 for(i=0;i<j;i++)
0230  p->pixdata[i]=0;
0231 if(position==0){
0232  p->refx=startx;
0233  p->refy=starty;
0234 }
0235 else{
0236  p->refx=startx+(endx-startx)/position;
0237  p->refy=starty+(endy-starty)/position;
0238 }
0239
0240 /*** Step 2 pixel buffer created, now draw on it ***/
0241 /* compute start pen position in 26.6 cartesian pixels */
0242 start.x = startx * 64;
0243 start.y = (hei-starty) * 64;
0244 /* set up transformation (a rotation here) */
0245 matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
0246 matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
0247 matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
0248 matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );
0249
0250 for ( n = 0; n < num_glyphs; n++ ){
0251  FT_Glyph  image;
0252  FT_Vector pen;
0253
0254  /* create a copy of the original glyph */
0255  error = FT_Glyph_Copy( glyphs[n].image, &image );
0256  if ( error ) continue;
0257
0258  /* transform copy (this will also translate it to the */
0259  /* correct position                                   */
0260  FT_Glyph_Transform( image, &matrix, &start );
0261//  FT_Glyph_Transform( image, &matrix, 0 );
0262
0263  /* check bounding box -- if the transformed glyph image */
0264  /* is not in our target surface, we can avoid rendering */
0265  FT_Glyph_Get_CBox( image, ft_glyph_bbox_pixels, &bbox );
0266
0267  if ( bbox.xMax <= 0 || bbox.xMin >= wid  ||
0268       bbox.yMax <= 0 || bbox.yMin >= hei )
0269          continue;
0270
0271  /* convert glyph image to bitmap (destroy the glyph */
0272  /* copy!)                                           */
0273  error = FT_Glyph_To_Bitmap(
0274         &image,
0275         ft_render_mode_normal,
0276         0,                /* no additional translation */
0277         1 );              /* destroy copy in "image"   */
0278  if ( !error ){
0279   FT_BitmapGlyph  bit = (FT_BitmapGlyph)image;
0280
0281   k=0;
0282   for(j=0;j<bit->bitmap.rows;j++)
0283    for(i=0;i<bit->bitmap.width;i++)
0284     if(bit->bitmap.buffer[k]!=0)
0285      p->pixdata[bit->left+i+wid*(hei-bit->top+j)]=bit->bitmap.buffer[k++];
0286      else k++;
0287
0288   FT_Done_Glyph( image );
0289  }
0290 }
0291 j=MakePixmap(2,wid,hei);
0292 XferPixmap(j,p);
0293 PastePixmap(j,0,0,3);
0294 DestroyPixmap(j);
0295 pdestroy(p);
0296 return 0;
0297} 
0298
0299int FDrawStrSize(char *c,int *wid,int *asc,int *dec)
0300{
0301 TGlyph glyphs[MAX_GLYPHS];  /* glyphs table           */
0302 PGlyph glyph;               /* current glyph in table */
0303 FT_UInt num_glyphs;
0304 FT_BBox bbox;
0305 int error;
0306 FT_UInt glyph_index;
0307 FT_Bool use_kerning;
0308 FT_UInt previous;
0309 int pen_x, pen_y, n;
0310 int num_chars;
0311 int i,j,k;
0312 int string_width,string_height;
0313 int target_width,target_height;
0314 int start_x,start_y;
0315 unsigned char c1,c2;
0316 char s[300];
0317 iconv_t cd;
0318 char *s2;
0319 char *s3;
0320
0321 /*** 0th phase : convert UTF-8 to EUC-JP ***/
0322 if(sjis){
0323  cd=iconv_open("UTF16BE","UTF-8");
0324  s2=c;
0325  s3=s;
0326  i=strlen(c);
0327  j=299;
0328  iconv(cd,&s2,&i,&s3,&j);
0329  iconv_close(cd);
0330  s[299-j]='\0';
0331 }
0332
0333 pen_x=0;   /* start at (0,0)! */
0334 pen_y=0;
0335
0336 num_glyphs=0;
0337 use_kerning=FT_HAS_KERNING( face );
0338
0339 previous=0;
0340
0341 if(sjis){
0342  num_chars=strlen(s);
0343  num_chars/=2;
0344 }
0345 else num_chars=strlen(c);
0346
0347 glyph = glyphs;
0348 for(n=0;n<num_chars;n++){
0349  if(sjis){
0350   c1=*((unsigned char *)s+2*n);
0351   c2=*((unsigned char *)s+2*n+1);
0352   //   euc2sjis(&c1,&c2);
0353   *(unsigned char *)(&i)=c2;
0354   *((unsigned char *)(&i)+1)=c1;
0355  }
0356  else i=c[n];
0357  glyph->index=FT_Get_Char_Index(face,i);
0358
0359  if ( use_kerning && previous && glyph->index ){
0360   FT_Vector  delta;
0361   FT_Get_Kerning(face,previous, glyph->index,
0362                            ft_kerning_default,&delta);
0363   pen_x+=delta.x>>6;
0364  }
0365
0366  /* store current pen position */
0367  glyph->pos.x=pen_x*64;
0368  glyph->pos.y=pen_y*64;
0369
0370
0371  /* load glyph image into the slot.  DO NOT RENDER IT! */
0372  error=FT_Load_Glyph(face,glyph->index,FT_LOAD_DEFAULT);
0373  if(error) continue;  /* ignore errors, jump to next glyph */
0374
0375  /* extract glyph image and store it in our table */
0376  error=FT_Get_Glyph(face->glyph,&glyph->image);
0377  if(error) continue;  /* ignore errors, jump to next glyph */
0378
0379  /* translate the glyph image now */
0380  FT_Glyph_Transform(glyph->image,0,&glyph->pos);
0381
0382  pen_x+=slot->advance.x>>6;
0383  previous=glyph->index;
0384
0385  /* increment number of glyphs */
0386  glyph++;
0387 }
0388 /* count number of glyphs loaded */
0389 num_glyphs=glyph-glyphs;
0390
0391 /* initialize string bbox to "empty" values */
0392 bbox.xMin=bbox.yMin= 32000;
0393 bbox.xMax=bbox.yMax=-32000;
0394
0395 /* for each glyph image, compute its bounding box, */
0396
0397 for(n=0;n<num_glyphs;n++){
0398  FT_BBox  glyph_bbox;
0399  FT_Glyph_Get_CBox( glyphs[n].image,ft_glyph_bbox_pixels, &glyph_bbox );
0400  if(glyph_bbox.xMin<bbox.xMin)
0401   bbox.xMin=glyph_bbox.xMin;
0402  if(glyph_bbox.yMin<bbox.yMin)
0403   bbox.yMin=glyph_bbox.yMin;
0404  if(glyph_bbox.xMax>bbox.xMax)
0405   bbox.xMax=glyph_bbox.xMax;
0406  if(glyph_bbox.yMax>bbox.yMax)
0407   bbox.yMax=glyph_bbox.yMax;
0408 }
0409 /* check that we really grew the string bbox */
0410 if(bbox.xMin>bbox.xMax){
0411  bbox.xMin=0;
0412  bbox.yMin=0;
0413  bbox.xMax=0;
0414  bbox.yMax=0;
0415 }
0416
0417 /* compute string dimensions in integer pixels */
0418 *wid=bbox.xMax-bbox.xMin;
0419 *asc=bbox.yMax;
0420 *dec=-bbox.yMin;
0421 return 0;
0422}
0423
0424/***********************************************************************
0425 FSetFont
0426
0427 font: 0 usrX11R6libX11fontsType1UTBI____.pfa
0428       1 usrX11R6libX11fontsType1UTB_____.pfa
0429       2 usrX11R6libX11fontsType1UTI_____.pfa
0430       3 usrX11R6libX11fontsType1UTRG____.pfa
0431       4 usrX11R6libX11fontsType1cour.pfa
0432       5 usrX11R6libX11fontsType1courb.pfa
0433       6 usrX11R6libX11fontsType1courbi.pfa
0434       7 usrX11R6libX11fontsType1couri.pfa
0435       8 usrX11R6libX11fontsType1lcdxmo.pfa
0436       9 usrX11R6libX11fontsType1lcdxmr.pfa
0437      10 usrX11R6libX11fontsType1lcdxro.pfa
0438      11 usrX11R6libX11fontsType1lcdxrr.pfa
0439      12 usrX11R6libX11fontsType1lcdxso.pfa
0440      13 usrX11R6libX11fontsType1lcdxsr.pfa
0441      14 usrsharefontsjaTrueTypewatanabe-mincho.ttf
0442      15 usrsharefontsjaTrueTypewadalab-gothic.ttf
0443 direc:
0444      direc=angle*100+position 
0445      Angle is 0 for the normal horizontal string, and measured
0446      in degree counter-clockwise.
0447      It can be specified with a digit below decimal point. 
0448      Position is either
0449        0 : current pen position is at the left side of the string 
0450        1 : current pen position is at the right side of the string or 
0451        2 : current pen position is at the middle of the string.
0452 size: character height in pixel
0453***********************************************************************/
0454int FSetFont(int font,int direc,int size)
0455{
0456// char *ff[]={"UTBI____.pfa","UTB_____.pfa","UTI_____.pfa","UTRG____.pfa",
0457//             "cour.pfa","courb.pfa","courbi.pfa","couri.pfa",
0458//             "lcdxmo.pfa","lcdxmr.pfa","lcdxro.pfa","lcdxrr.pfa",
0459//             "lcdxso.pfa","lcdxsr.pfa","watanabe-mincho.ttf","wadalab-gothic.ttf"};
0460// char *fd[]={"/usr/X11R6/lib/X11/fonts/Type1/","/usr/share/fonts/ja/TrueType/"};
0461 char *ff[]={"UTBI____.pfa","UTB_____.pfa","UTI_____.pfa","UTRG____.pfa",
0462             "cour.pfa","courb.pfa","courbi.pfa","couri.pfa",
0463             "l047033t.pfa","l047013t.pfa","l049033t.pfa","l049013t.pfa",
0464             "l048033t.pfa","l048013t.pfa","kochi-mincho-subst.ttf","kochi-gothic-subst.ttf"};
0465 char *fd[]={"/usr/X11R6/lib/X11/fonts/Type1/","/usr/share/fonts/japanese/TrueType/"};
0466 char file[100];
0467 int i;
0468
0469 if(font<14){
0470  strcpy(file,fd[0]);
0471  sjis=0;
0472 }
0473 else if(font<16){
0474  strcpy(file,fd[1]);
0475  sjis=1;
0476 }
0477 else return 1;
0478 strcat(file,ff[font]);
0479
0480 if(library==0) FT_Init_FreeType(&library);
0481 FT_New_Face(library,file,0,&face);
0482 if(font<14){
0483  i=strlen(file);
0484  strcpy(&file[i-3],"afm");
0485  FT_Attach_File(face,file);
0486 }
0487
0488 if(sjis) FT_Select_Charmap(face,ft_encoding_sjis);
0489 FT_Set_Pixel_Sizes(face,0,size);
0490 slot = face->glyph;
0491 position=direc%10;
0492 ang=direc-position;
0493 ang/=100.;
0494 angle=ang*0.017453;
0495}
0496
0497int fttest()
0498{
0499 FSetFont(8,3001,40);
0500 FDrawStr("abcdefghi");
0501 return 0;
0502}
0503