#include <stdio.h> #include <math.h> /* usage */ /* type1tomf psfile > mffile */ int nohint; main(ac,ag) char **ag; { FILE *fp; int len,kcode; char buf[4096]; if(ac<2)exit(1); if(!strcmp(ag[1],"-nohint"))nohint=1,ag++; if((fp=fopen(ag[1],"r"))==NULL){ fprintf(stderr,"File %s is not found\n",ag[1]); exit(1); } print_header(); while(fgets(buf,4096,fp)!=NULL){ len=strlen(buf); if(buf[0]=='<' && !strncmp(buf+len-6 ,"CompD",5)){ kcode=strtol(buf+len-12,NULL,16); print_kanji(kcode,buf); } } printf("end"); fclose(fp); return 0; } print_header() { printf("font_size 10pt#;\n"); printf("mode_setup;\n"); printf("turningcheck := 0;\n"); } print_kanji_header(kcode) { printf("beginchar(%d,10pt#,10pt#,0pt#);\n",kcode&255); } int hex2bin(hexstr,binstr) char *hexstr; unsigned char *binstr; { int len,c; for(len=0,hexstr++;*hexstr!='>'&&*hexstr;hexstr+=2,len++){ c=(*hexstr>='a'?*hexstr-'a'+10:*hexstr-'0'); *binstr++ = (c<<4)|(*(hexstr+1)>='a'?*(hexstr+1)-'a'+10:*(hexstr+1)-'0'); } return len; } decrypt_str(cipher,plain,len) unsigned char *cipher,*plain; { unsigned short r=4330,c1=52845,c2=22719; while(--len>=0){ *plain++=(*cipher ^ (r>>8)); r=(*cipher++ +r)*c1+c2; } } show_charstr(plain,len) unsigned char *plain; { unsigned char *limit=plain+len,uc; int n; while(plain<limit){ uc= *plain++; if(32 <=uc && uc<=246){ printf("Int %d\n",(int)uc-139); } else if(247<=uc && uc<=250){ printf("Int %d\n",((int)uc-247)*256+(*plain++)+108); } else if(251<=uc && uc<=254){ printf("Int %d\n",-((int)uc-251)*256-(*plain++)-108); } else if(uc==255){ printf("Int %d\n", (*plain<<24)|(*(plain+1)<<16)|(*(plain+2)<<8)|(*(plain+3))); plain+=4; } else switch (uc){ case 14:printf("endchar\n");break; case 13:printf("hsbw\n");break; case 12: switch(*plain++){ case 6: printf("seac\n");break; case 7: printf("sbw\n");break; case 0: printf("dotsection\n");break; case 2: printf("hstem3\n");break; case 1: printf("vstem3\n");break; case 12: printf("div\n");break; case 16: printf("callothersubr\n");break; case 17: printf("pop\n");break; case 33: printf("setcurrentpoint\n");break; } break; case 9: printf("closepath\n");break; case 6: printf("hlineto\n");break; case 22: printf("hmoveto\n");break; case 31: printf("hcvcurveto\n");break; case 5: printf("rlineto\n");break; case 21: printf("rmoveto\n");break; case 8: printf("rrcurveto\n");break; case 30: printf("vhcurveto\n");break; case 7: printf("vlineto\n");break; case 4: printf("vmoveto\n");break; case 1: printf("hstem\n");break; case 3: printf("vstem\n");break; case 10: printf("callsubr\n");break; case 11: printf("return\n");break; } } } #define STACKSIZE 1024 int stack[STACKSIZE]; #define PUSH(x) (*--sp=(x)) #define DISCARD(n) (sp+=n) struct point { int tag,x,y; } points[1024]; /* tags */ #define NONE 0 #define LINE 1 #define BEZIER 2 int lcount=0; #define PI 3.14159265358979 #define PI2 (PI*2) double difftheta(t1,t2) double t1,t2; { double difft=t2-t1; if(difft<-PI)return (difft+PI2); else if(difft>PI) return (difft-PI2); else return difft; } double allangle(p) { int i; double t0,t1,t2,allt; for(i=0;points[i+1].y==points[i].y && points[i+1].x==points[i].x;i++); t0=t1=atan2((double)(points[i+1].y-points[i].y),(double)(points[i+1].x-points[i].x)); i++; for(allt=0.0;i<p-1;i++){ if(points[i+1].y!=points[i].y || points[i+1].x!=points[i].x){ t2=atan2((double)(points[i+1].y-points[i].y),(double)(points[i+1].x-points[i].x)); allt+=difftheta(t2,t1); /* fprintf(stderr,"allangle=%f,t1=%f,t2=%f\n",allt,t1,t2); */ t1=t2; } } if(points[0].y!=points[i].y || points[0].x!=points[i].x){ t2=atan2((double)(points[0].y-points[i].y),(double)(points[0].x-points[i].x)); allt+=difftheta(t2,t1); } allt+=difftheta(t0,t2); /* fprintf(stderr,"allangle=%f\n",allt); */ return allt; } notline(x0,y0,x1,y1,x2,y2,x3,y3) { int dx=x3-x0,dy=y3-y0,dx0=x1-x0,dy0=y1-y0,dx3=x3-x2,dy3=y3-y2; double t0,t3,difft; if(dx*dx+dy*dy>50)return 1; if(dy0==0 && dx0==0){ if((dy3==0 && dx3==0)||(x2==x0 && y2==y0)) return 0; dx0=x2-x0;dy0=y2-y0; } t0=atan2((double)dy0,(double)dx0); if(dx3==0 && dy3==0){ if((x1==x3 && y1==y3)) return 0; dx3=x3-x1;dy3=y3-y1; } t3=atan2((double)dy3,(double)dx3); difft=difftheta(t3,t0); if(difft<-0.4 || difft>0.4) return 1; return 0; } flush_point(p) { int i; if(p>0){ for(i=0;i<p;i++){ print_x(lcount+i,points[i].x); print_y(lcount+i,points[i].y); } #if 0 if(allangle(p)<0.0) printf("fill "); else printf("unfill "); #endif printf("fill "); printf("(x%d,y%d)",lcount,lcount); for(i=1;i<p;i++){ switch (points[i].tag){ case BEZIER: if(notline(points[i-1].x,points[i-1].y, points[i].x,points[i].y, points[i+1].x,points[i+1].y, points[(i+2)%p].x,points[(i+2)%p].y)){ printf(" .. controls (x%d,y%d) and (x%d,y%d)", lcount+i,lcount+i,lcount+i+1,lcount+i+1); if(i+3>p) printf("\n"); else printf(" .. (x%d,y%d)\n", lcount+i+2,lcount+i+2); } else { printf(" -- (x%d,y%d)\n", lcount+(i+2)%p,lcount+(i+2)%p); } i+=2; break; case LINE: printf(" -- (x%d,y%d)\n",lcount+i,lcount+i); break; } } if(points[p-1].x!=points[0].x || points[p-1].y!=points[0].y){ printf(" .. (x%d,y%d)",lcount,lcount); } printf(" .. cycle;\n"); lcount+=p; } } struct stems{ int from,width,n; } hstems[256],vstems[256]; int hstem,vstem,checked; int compstem(c1,c2) struct stems *c1,*c2; { return c1->from - c2->from; } int toph,both,topv,botv; check_stems() { int i; if(hstem){ hstems[hstem].from=0; hstems[hstem++].width=0; hstems[hstem].from=1000; hstems[hstem++].width=0; qsort(hstems,hstem,sizeof(struct stems),compstem); for(i=0;i<hstem;i++){ hstems[i].n=lcount+i*2; printf("y%d=round (%d/1000.0*h);\n",lcount+i*2,hstems[i].from); if(i!=hstem-1) printf("y%d=round (y%d+min((%d/1000.0*w),max(1,(%d/1000.0*w))));\n", lcount+i*2+1, lcount+i*2, hstems[i+1].from-hstems[i].from, hstems[i].width); else printf("y%d=round (y%d+max(1,(%d/1000.0*w)));\n", lcount+i*2+1, lcount+i*2, hstems[i].width); } lcount+=hstem*2; } if(vstem){ vstems[vstem].from=0; vstems[vstem++].width=0; vstems[vstem].from=1000; vstems[vstem++].width=0; qsort(vstems,vstem,sizeof(struct stems),compstem); for(i=0;i<vstem;i++){ vstems[i].n=lcount+i*2; printf("x%d=round (%d/1000.0*h);\n",lcount+i*2,vstems[i].from); if(i!=vstem-1) printf("x%d=round (x%d+min((%d/1000.0*h),max(1,(%d/1000.0*h))));\n", lcount+i*2+1,lcount+i*2, vstems[i+1].from-vstems[i].from,vstems[i].width); else printf("x%d=round (x%d+max(1,(%d/1000.0*h)));\n", lcount+i*2+1,lcount+i*2, vstems[i].width); } lcount+=vstem*2; } checked=1; } print_x(index,x) { int i; if(checked && vstem){ for(i=1;i<vstem;i++){ if(x<vstems[i].from){ printf("x%d=x%d+(x%d-x%d)/%d*%d;\n",index, vstems[i-1].n+1,vstems[i].n,vstems[i-1].n+1, vstems[i].from-vstems[i-1].from-vstems[i-1].width, x-vstems[i-1].from-vstems[i-1].width); return; } else if(x<=vstems[i].from+vstems[i].width){ printf("x%d=x%d+(x%d-x%d)/%d*%d;\n",index, vstems[i].n,vstems[i].n+1,vstems[i].n, vstems[i].width, x-vstems[i].from); return; } } printf("x%d=(%d/1000.0*w);\n",index,x); } else printf("x%d=(%d/1000.0*w);\n",index,x); } print_y(index,y) { int i; if(checked && hstem){ for(i=1;i<hstem;i++){ if(y<hstems[i].from){ printf("y%d=y%d+(y%d-y%d)/%d*%d;\n",index, hstems[i-1].n+1,hstems[i].n,hstems[i-1].n+1, hstems[i].from-hstems[i-1].from-hstems[i-1].width, y-hstems[i-1].from-hstems[i-1].width); return; } else if(y<=hstems[i].from+hstems[i].width){ printf("y%d=y%d+(y%d-y%d)/%d*%d;\n",index, hstems[i].n,hstems[i].n+1,hstems[i].n, hstems[i].width, y-hstems[i].from); return; } } printf("y%d=(%d/1000.0*h);\n",index,y); } else printf("y%d=(%d/1000.0*h);\n",index,y); } mf_parse_stem(plain,len) unsigned char *plain; { unsigned char *limit=plain+len,uc; int n; int *sp=stack+STACKSIZE; int x=0,y=0,p=0; while(plain<limit){ uc= *plain++; if(32 <=uc && uc<=246) PUSH((int)uc-139); else if(247<=uc && uc<=250) PUSH(((int)uc-247)*256+(*plain++)+108); else if(251<=uc && uc<=254) PUSH(-((int)uc-251)*256-(*plain++)-108); else if(uc==255){ PUSH((*plain<<24)|(*(plain+1)<<16)|(*(plain+2)<<8)|(*(plain+3))); plain+=4; } else switch (uc){ case 14:/* printf("endchar\n"); */ break; case 13:/* printf("hsbw\n"); */ DISCARD(2); break; case 12: switch(*plain++){ case 6:/* printf("seac\n"); */ DISCARD(5); break; case 7:/* printf("sbw\n"); */ DISCARD(4); break; case 0: /* printf("dotsection\n"); */ break; case 2:/* printf("hstem3\n"); */ DISCARD(6); break; case 1:/* printf("vstem3\n"); */ DISCARD(6); break; case 12:/* printf("div\n"); */ DISCARD(2); break; case 16:/* printf("callothersubr\n"); */ DISCARD(sp[1]+2); break; case 17:/* printf("pop\n"); */ DISCARD(1); break; case 33:/* printf("setcurrentpoint\n"); */ DISCARD(2); break; } break; case 9: /* printf("closepath\n"); */ break; case 6: /* printf("hlineto\n"); */ DISCARD(1); break; case 22: /* printf("hmoveto\n"); */ DISCARD(1); break; case 31:/* printf("hvcurveto\n"); */ DISCARD(4); break; case 5:/* printf("rlineto\n"); */ DISCARD(2); break; case 21:/* printf("rmoveto\n"); */ DISCARD(2); break; case 8:/* printf("rrcurveto\n"); */ DISCARD(6); break; case 30:/* printf("vhcurveto\n"); */ DISCARD(4); break; case 7: /* printf("vlineto\n"); */ DISCARD(1); break; case 4:/* printf("vmoveto\n"); */ DISCARD(1); break; case 1:/* printf("hstem\n"); */ hstems[hstem].from=sp[1]; hstems[hstem++].width=sp[0]; DISCARD(2); break; case 3:/* printf("vstem\n"); */ vstems[vstem].from=sp[1]; vstems[vstem++].width=sp[0]; DISCARD(2); break; case 10:/* printf("callsubr\n"); */ DISCARD(1); break; case 11:/* printf("return\n"); */ break; } } check_stems(); } mf_charstr(plain,len) unsigned char *plain; { unsigned char *limit=plain+len,uc; int n; int *sp=stack+STACKSIZE; int x=0,y=0,p=0; while(plain<limit){ uc= *plain++; if(32 <=uc && uc<=246) PUSH((int)uc-139); else if(247<=uc && uc<=250) PUSH(((int)uc-247)*256+(*plain++)+108); else if(251<=uc && uc<=254) PUSH(-((int)uc-251)*256-(*plain++)-108); else if(uc==255){ PUSH((*plain<<24)|(*(plain+1)<<16)|(*(plain+2)<<8)|(*(plain+3))); plain+=4; } else switch (uc){ case 14:/* printf("endchar\n"); */ flush_point(p);p=0; break; case 13:/* printf("hsbw\n"); */ DISCARD(2); break; case 12: switch(*plain++){ case 6:/* printf("seac\n"); */ DISCARD(5); break; case 7:/* printf("sbw\n"); */ DISCARD(4); break; case 0: /* printf("dotsection\n"); */ break; case 2:/* printf("hstem3\n"); */ DISCARD(6); break; case 1:/* printf("vstem3\n"); */ DISCARD(6); break; case 12:/* printf("div\n"); */ DISCARD(2); break; case 16:/* printf("callothersubr\n"); */ DISCARD(sp[1]+2); break; case 17:/* printf("pop\n"); */ DISCARD(1); break; case 33:/* printf("setcurrentpoint\n"); */ DISCARD(2); break; } break; case 9: /* printf("closepath\n"); */ flush_point(p);p=0; break; case 6: /* printf("hlineto\n"); */ x+= *sp++; points[p].tag=LINE; points[p].x=x; points[p++].y=y; break; case 22: /* printf("hmoveto\n"); */ x+= *sp++; flush_point(p);p=0; points[p].tag=NONE; points[p].x=x; points[p++].y=y; break; case 31:/* printf("hvcurveto\n"); */ x+= sp[3]; points[p].tag=BEZIER; points[p].x=x; points[p++].y=y; x+=sp[2];y+=sp[1]; points[p].tag=BEZIER; points[p].x=x; points[p++].y=y; y+=sp[0]; points[p].tag=BEZIER; points[p].x=x; points[p++].y=y; DISCARD(4); break; case 5:/* printf("rlineto\n"); */ y+= *sp++;x+= *sp++; points[p].tag=LINE; points[p].x=x; points[p++].y=y; break; case 21:/* printf("rmoveto\n"); */ y+= *sp++;x+= *sp++; flush_point(p);p=0; points[p].tag=NONE; points[p].x=x; points[p++].y=y; break; case 8:/* printf("rrcurveto\n"); */ x+= sp[5];y+=sp[4]; points[p].tag=BEZIER; points[p].x=x; points[p++].y=y; x+=sp[3];y+=sp[2]; points[p].tag=BEZIER; points[p].x=x; points[p++].y=y; x+=sp[1];y+=sp[0]; points[p].tag=BEZIER; points[p].x=x; points[p++].y=y; DISCARD(6); break; case 30:/* printf("vhcurveto\n"); */ y+=sp[3]; points[p].tag=BEZIER; points[p].x=x; points[p++].y=y; x+=sp[2];y+=sp[1]; points[p].tag=BEZIER; points[p].x=x; points[p++].y=y; x+=sp[0]; points[p].tag=BEZIER; points[p].x=x; points[p++].y=y; DISCARD(4); break; case 7: /* printf("vlineto\n"); */ y+= *sp++; points[p].tag=LINE; points[p].x=x; points[p++].y=y; break; case 4:/* printf("vmoveto\n"); */ y+= *sp++; flush_point(p);p=0; points[p].tag=NONE; points[p].x=x; points[p++].y=y; break; case 1:/* printf("hstem\n"); */ DISCARD(2); break; case 3:/* printf("vstem\n"); */ DISCARD(2); break; case 10:/* printf("callsubr\n"); */ DISCARD(1); break; case 11:/* printf("return\n"); */ break; } } } print_kanji(kcode,buf) int kcode; char *buf; { int len; unsigned bbuf[4096]; unsigned plain[4096]; len=hex2bin(buf,bbuf); decrypt_str(bbuf,plain,len); print_kanji_header(kcode); lcount=hstem=vstem=checked=0; if(!nohint) mf_parse_stem(plain,len); mf_charstr(plain,len); printf("endchar;\n"); }