#include <stdio.h> #include <sys/types.h> #include <sys/time.h> #ifdef MSDOS #define WB "wb" #else #define WB "w" #endif #define CODE_SIZE 4418 #define DEFAULTTHRESH 10.0 double thresh=DEFAULTTHRESH; struct { char *str; int len; } allkanji[94*94]; char *vfbase="ZFont"; usage(cmd) char *cmd; { fprintf(stderr,"usage: %s [-thresh threshold] [-base basename] [file...]\n",cmd); fprintf(stderr," -thresh .threshold default %f\n",DEFAULTTHRESH); fprintf(stderr," -base .baesname default %s\n","ZFont"); exit(1); } main(ac,ag) char **ag; { double strtod(); int i; for(i=1;i<ac;i++){ if(*ag[i]=='-'){ if(!strcmp(ag[i]+1,"thresh")) thresh=strtod(ag[++i],0); else if(!strcmp(ag[i]+1,"base")) vfbase=ag[++i]; else usage(ag[0]); } else{ parsekanji(ag[i]); } } output_zeit(1); output_zeit(2); exit(0); } int hex1(x) { return (x>='a'?x-'a'+10:(x>='A'?x-'A'+10:x-'0')); } char *allocbin(buf,len) char *buf; { int i; char *cptr,*malloc(); if((cptr=malloc(len))==NULL){ fprintf(stderr,"Failed in malloc()\n"); exit(1); } for(i=0;i<len;i++) cptr[i]=(hex1(buf[i*2])<<4)|hex1(buf[i*2+1]); return cptr; } parsekanji(filename) char *filename; { FILE *fd; int len,kcode,koffset,klen; char buf[4096]; if((fd=fopen(filename,"r"))==NULL){ fprintf(stderr,"File %s is not found\n",filename); exit(1); } while(fgets(buf,4096,fd)!=NULL){ len=strlen(buf); if(buf[0]=='<' && !strncmp(buf+len-6 ,"CompD",5)){ kcode=strtol(buf+len-12,NULL,16); koffset=(((kcode>>8)&255)-0x21)*94+((kcode&255)-0x21); klen=(len-16)/2; allkanji[koffset].str=allocbin(buf+1,klen); allkanji[koffset].len=klen; } } fclose(fd); } int offsets[CODE_SIZE]; output_zeit(level) int level; { char filename[256]; FILE *fd; int kbase,klimit,offset,i; long last; sprintf(filename,"%s.vf%d",vfbase,level); if((fd=fopen(filename,WB))==NULL){ fprintf(stderr,"Failed opening file %s\n",filename); exit(1); } fseek(fd,(long)(CODE_SIZE*4+2),0); if(level==1){ kbase=0; klimit=0x5e*(0x50-0x21); } else { kbase=0x5e*(0x50-0x21); klimit=0x5e*(0x75-0x50); } for(offset=i=0;i<klimit;i++){ if(allkanji[i+kbase].len>0){ offsets[i]=offset; offset+=zeit_character(fd,allkanji[kbase+i].str,allkanji[kbase+i].len); } else offsets[i]= 0xffffffff; } last=ftell(fd); fseek(fd,0L,0); output_short(fd,level); for(i=0;i<CODE_SIZE;i++) output_long(fd,offsets[i]); fseek(fd,last,0); fclose(fd); } output_short(fd,val) FILE *fd; short val; { putc(val,fd); putc(val>>8,fd); } output_long(fd,val) FILE *fd; long val; { putc(val,fd); putc(val>>8,fd); putc(val>>16,fd); putc(val>>24,fd); } int rest; int outbuf; int count; init_10() { rest=0; count=0; } output_10(fd,val) FILE *fd; { outbuf<<=10; outbuf|=(val&0x3ff); rest+=10; if(rest>=16){ rest-=16; putc(outbuf>>rest,fd); putc(outbuf>>(rest+8),fd); count+=2; } } output_x(fd,val) FILE *fd; { if(val<0) val=0; else if(val>1022) val=1022; return output_10(fd,val); } output_y(fd,val) FILE *fd; { val=1000-val; if(val<0) val=0; else if(val>1022) val=1022; return output_10(fd,val); } flush_10(fd) FILE *fd; { if(rest>0){ if(rest<6)output_10(fd,0); output_10(fd,0); } return(count); } zeit_character(fd,str,len) FILE *fd; char *str; { unsigned plain[4096]; decrypt_str(str,plain,len); init_10(); mf_charstr(fd,plain,len); return flush_10(fd); } 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; } } #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 output_bezier(fd,x0,y0,x1,y1,x2,y2,x3,y3) FILE *fd; double x0,y0,x1,y1,x2,y2,x3,y3; { double minx,miny,maxx,maxy,tempx,tempy; minx=(x0>x1?x1:x0); minx=(x2>minx?minx:x2); minx=(x3>minx?minx:x3); miny=(y0>y1?y1:y0); miny=(y2>miny?miny:y2); miny=(y3>miny?miny:y3); maxx=(x0<x1?x1:x0); maxx=(x2<maxx?maxx:x2); maxx=(x3<maxx?maxx:x3); maxy=(y0<y1?y1:y0); maxy=(y2<maxy?maxy:y2); maxy=(y3<maxy?maxy:y3); if(maxx-minx<thresh || maxy-miny<thresh){ output_x(fd,(int)(x3+0.5)); output_y(fd,(int)(y3+0.5)); return; } else{ tempx=0.125*x0+0.375*x1+0.375*x2+0.125*x3; tempy=0.125*y0+0.375*y1+0.375*y2+0.125*y3; output_bezier(fd,x0,y0, 0.5*x0+0.5*x1, 0.5*y0+0.5*y1, 0.25*x0+0.5*x1+0.25*x2, 0.25*y0+0.5*y1+0.25*y2, tempx,tempy); output_bezier(fd,tempx,tempy, 0.25*x1+0.5*x2+0.25*x3, 0.25*y1+0.5*y2+0.25*y3, 0.5*x2+0.5*x3, 0.5*y2+0.5*y3, x3,y3); } } flush_point(fd,p) FILE *fd; { int i; if(p>0){ output_x(fd,points[0].x); output_y(fd,points[0].y); for(i=1;i<p;i++){ switch (points[i].tag){ case BEZIER: output_bezier(fd, (double)points[i-1].x,(double)points[i-1].y, (double)points[i].x,(double)points[i].y, (double)points[i+1].x,(double)points[i+1].y, (double)points[i+2].x,(double)points[i+2].y); i+=2; break; case LINE: output_x(fd,points[i].x); output_y(fd,points[i].y); } } output_10(fd,0x3ff); output_10(fd,0x3ff); } } mf_charstr(fd,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(fd,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(fd,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(fd,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(fd,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(fd,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; } } output_10(fd,0x3ff); output_10(fd,0x3ff); }