|
||
|
||
| 摘要 该文根据WPS中曲线字体的结构,利用AutoCAD本身的功能 和其ADS接口,提供了在AutoCAD中生成曲线汉字的方法,并给出了相应 的C语言源程序清单。 关键字 曲线字体 ADS 拟合 Bezier曲线 一、引言 AutoCAD是目前微机上广泛使用的绘图平台,其上使用的汉字常常 是通过形文件(.shx)来实现的,虽然采用的是矢量字体,但放大后总不 够满意,而且也不便于对笔划进行编辑或对空心字进行填充。现在的W PS中提供了多种优美的中文曲线字体(.ps文件),这些字体文件中存放 的是相应字体的轮廓描述信息。如果按其中的信息来绘制图案,自然 可获得优美的轮廓汉字,并可填充或编辑。关于中文曲线字体的结构, 《微电脑世界》1996.1中袁国强等撰写的《揭开PostScript字体的奥 秘》一文中已经作了详细介绍,本人参照其内容要点,结合AutoCAD的 功能特点,利用其ADS开发系统作了绘制曲线汉字的尝试。 二、AutoCAD处理曲线字体的有效性 曲线字体中所使用的曲线有两种,一种是由3点控制的二次Bezier 曲线,另一种是由4点控制的3次Bezier曲线。通过数学推导可证明,只 要把控制点作适当变换,可用3次Bezier曲线精确地代替二次Bezier曲 线,这样,实质上可统一为由4点控制的3次Bezier曲线。而在AutoCAD 中恰好有拟合曲线的功能,当系统变量"SplieType"的值设置成6时,笔 者经过精确测试,当控制点为4时,系统是按3次Bezier曲线来以分段拟 合曲线的(尽管书上声称为3次B-Spline),且分段数是由系统变量"Spl ineSegs"决定的,当该值取为负值时还能在分段的基础上用圆弧拟合, 达到了非常光滑的程度。关于曲线字体中的直接处理,则更为容易。 因此,用AutoCAD来处理曲线汉字将有独到之处。另外,AutoCAD从R11 版开始提供了ADS接口,即支持C语言编程。这样,根据曲线字体的结构 ,用C语言来处理二进制数据,而用AutoCAD来处理相应的轮廓绘制,就 能有效地展示曲线汉字的风彩。 三、程序清单 为了减少篇幅,程序中只考虑了用区位码输入单个汉字的方法,读 者可对程序作适当修改以便使程序能处理汉字串等。关于ADS程序的 编译和链接,可参考有关文献。笔者所编程序分别用Watcom C9.01和T urbo C++3.1编译和链接,并在AutoCAD R12 for DOS和for Windows中 调试通过。 /*文件名:PSHZ.C 使用方法: 在AutoCAD下,先用SETVAR命令把有关系统变量设置如下: "SplineType"=6(样条类型) "SplineSegs"=-8(用圆弧分段代替样条) "SnapMode"=0(关掉目录捕捉) "SplFrame"=0(不显示控制边框) 再通过xload函数装入pshz.exp或pshz.exe,在命令状态下打入PS HZ,并根据提示陆续输入曲线字体文件名、区位码、左上角定位点及 文字高度。 */ #include #include #include"abslib" #define COPY-POINT(Dp,Sp){(Dp)[0]=(Sp)[0];(Dp)[1]=(Sp)[1 ]; } #define INDEX(Arr) ((long(Arr)[2]*65536+(long)(Arr)[1]*2 56+(long)(Arr)[0]) unsigned int mainCount,mainBlockSize,subCount,subBlockSi ze; unsigned char *mainBlock,*subBlock; ads-real scaleX,scaleY; void main(int,char **); int dofun(void); int funcload(void); int pshz(struct resbuf *rb); unsigned char readBlock(int); int drawHandle(int,unsigned char,ads real, ads real, ads point, ads point); int partHandle(FLIE *,unsigned char *,long,ads-point); void main(argc,argv) int argc; char *argv[]; { short scode=RSRSLT; int stat; char errmsg[80]; ads-int(argc,argv); for(;;) { if((stat=ads-link(scode))<0) { sprinft(errmsg,"PSHZ:bad status from ads-link()=%d\n",st at); exit(1); } scode=RSRSLT; switch(stat) { case RQXLOAD: scode=funcload()==RTNORM?RSRSLT:RSERR; break; case RQSUBR: scode=dofun()==RTNORM?RSRSLT:RSERR; break; default; break; }}} static int funcload(){if(!ads-defun("c:pshz",0)) return RTERROR; return RTNORM; } static int dofun(){struct resbuf *rb; if(!ads-getfuncode()==0{ ads-fail("Received nonexistent function code."); return RTERROR; } rb=ads getargs(); return pshz(rb); } static int pshz(rb)struct resbuf *rb; { int qw,qm,wm; ads-point refP,curP; char fileName[128]; long firstIndex,secondIndex,wordOffset; unsigned char indexValue[2][3],partData[11]; FILE *fp; int i,j; char controlWord; ads-getstring(0,"\npsFontFileName(eg.KTDOT.PS):",fileNam e); ads-getint("\nQuWeiMa:",&qw); ads-getpoint(NULL,"\nupperleft point:",refp); ads getreal("\nText height:",&scaleY); scaleY/=160.0; scaleX=scaleY; scaleY=-scaleY; mainCount=0; if(!(fp=fopen(fileName,"rb"))){ ads-printf("Cannot open %s file\n",fileName); return RTERROR; } wordOffset=72*94*3; fseek(fp,wordOffset,SEEK-SET); fread(indexValue[0],3,1,fp); secondIndex=INDEX(indexValue[0]); qm=qw/100; wm=qw%100; wordOffset=(((long)qm-16)*94+wm-1)*3; fseek(fp,wordOffset,SEEK-SET); fread(indexValue[0],3,1,fp); fread(indexValue[1],3,1,fp); firstIndex=INDEX(indexValue[0]); mainBlockSize=INDEX(indexValue[1])-firstIndex; mainBlock=(unsigned char *)malloc(mainBlockSize); if(!mainBlock){ ads-printf("Out of memory!\n"); goto err2; } fseek(fp,firstIndex,SEEK SET); fread(mainBlock,1,mainBlockSize,fp); while(mainCount<2*mianBlockSize) { controlWord=readBlock(0); if(controlWord<=7) { if(drawHandle(0,controlWord,1.0,1.0,refP,curP)!=RTNORM) goto err1; } else { partData[0]=controlWord; for(i=1;i<11;i++) partData=readBlock(0); if(partII andle(fp,partData,secondIndex,refP)!=RTNORM) goto err1; }} free(mainBlock); fclose(fp); return RTNORM; err1: free(mainBlock); err2: fclose(fp); return RTERROR; } unsigned char readBlock(int SubOrMain) { if(subOrMain==0) return (0x0f & (mainBlock[mainCount/2]>>((1-((mainCount+ +)%2))*4))); return (0x0f & (subBlock[subCount/2]>>((1-((subCount++)% 2))*4))); } int drawHandle(blkNo,controlWord,facX,facY,refP,curP) int blkNo; unsigned char controlWord; ads-real facX,facY; ads-point refP,curP; { int i,j; ads-point p[4],scaleP; scaleP[0]=scaleX*facX; scaleP[1]=scaleY*facY; switch(controlWord) { case 0: for(i=0;i<2;i++) { p[0]=(int)readBlock(blkNo)*16+readBlock(blkNo); p[0]*=scaleP; p[0]+=refP; } COPY POINT (curP,p[0]); break; case 1: case 2: i=controlWord-1; j=(i+1)%2; p[0]=(int)readBlock(blkNo)*16+readBlock(blkNo); p[0]*=scaleP; p[0]+=refPp[0][j]=curP[j]; goto line; case 3: for(i=0;i<2;i++) { p[0]=(int)readBlock(blkNo)*16+readBlock(blkNo); p[0]*=scaleP; p[0]+=refP; } line; ads-command(RTSTR,"pline",RTPOINT,curP,RTPOINT,p[0],RTST R,"",0); COPY POINT(curP,p[0]); break; case 4: case 5: COPY-POINT(p[0],curP); for(i=1;i |
||
| :查看相关: | ||