『楼 主』:
UCDOS 5.0 版本以上曲线字库汉字显示程序源代码
若字库为5.0版,应去掉下面一段代码
if(j==1){ //若为汉字,调整地址偏移值
hz.offset-=0x10000000;
} 希望大家能够喜欢!!!!!!!
#include "d:\borland\user\src\graphics.h"
#include "d:\borland\user\src\graphics.c"
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <mem.h>
#include <alloc.h>
#include <dir.h>
#include <dos.h>
#include <stdlib.h>
#define baseSize 250 //此值越大,字体越小,原值为168
#define portion 100 //100
FILE *fpfh,*fphz,*fpe,*fp;
int X0,Y0,xRange,yRange,curX,curY;
int newX0,newY0,newxRange,newyRange;
unsigned char *wordCont_0=NULL,*wordCont_8=NULL;
unsigned bytesNum_0,bytesNum_8;
unsigned char myread(void);
void control(int *xx,int *yy,unsigned char controlWord,int nowxRange,
int nowyRange,int nowX0,int nowY0,int call_8_0);
void showhz(char *fontfileName,unsigned long col);
void b3_4(int *x,int *y,unsigned long col);
void b3_3(int *x,int *y,unsigned long col);
int readbyte(void);
int readcount;
static unsigned char next; //用于读取字节高四位、低四位的标志,1读高位,0读低位
typedef struct _hz{
unsigned long offset; //4字节
unsigned int length; //2字节
}hz_;
hz_ hz;
unsigned char hzdata[1024]; //用于读取字型数据
void main(void)
{
unsigned char *hzstring="然字Mm骤啊H骤g9酆8G字,汉,然。!!戆";//戆您原回骤然燃";//"共有汉字个骤";原骤戆啊汉字
long color;
initgraph(VBE480_16M);
X0=Y0=1;xRange=yRange=152;//原值为152
showhz(hzstring,rgbcolor(255,0,0));
getch();
cleardevice();
closegraph();
}
void showhz(char *hzstring,unsigned long col)
{
unsigned long oldcolor;
unsigned long wordOffset;
unsigned char qm,wm;
int bx,by; //用于记录笔画的起始点坐标
int xx[4],yy[4],controlWord,i,j,m=0;
char ch,cha,chx,chy,chxx,chyy;
char mark1_x,mark1_y,mark2_x,mark2_y,mark3_x,mark3_y;
char *fontFileName="HZKPSKTJ";//HZKPSXKJ";//HZKPSST.GBK";//"HZKPSHTJ";//"HZKPSFSJ";//"HZKPSXBJ";HZKPSKTJ;HZKPSY3J;ASCPS;HZKPST;HZKPSDHJ,HZKPSYTJ
oldcolor=getcolor();
setcolor(col);
if((fpfh=fopen("HZKPST","rb"))==NULL) { //打开中文符号曲线字库
printf("Cannot open %s file\n","HZKPST");
exit(0);
}
if((fphz=fopen(fontFileName,"rb"))==NULL) { //打开中文曲线字库,若为GBK字库,则打开的是GBK字库
printf("Cannot open %s file\n",fontFileName);
exit(0);
}
if((fpe=fopen("ASCPS","rb"))==NULL) { //打开英文曲线字库
printf("Cannot open %s file\n","ASCPS");
exit(0);
}
i=0;
while(i<strlen(hzstring))
{
readcount=0;
next=0;
if((hzstring[i]&0x80)==0x80){ //判断是否为汉字,相等,即最高位是1,则为汉字
qm=hzstring[i]-0xa0; //区码
wm=hzstring[i+1]-0xa0; //位码
j=1; //作为汉字的标志,用于调整地址偏移
if(strcmp(strrchr(fontFileName, '.')+1,"GBK")==0){ //首先找到最后一个'.'的位置,加1使指针指向'.'后的第一个字符,然后进行比较,判断是否是GBK字库
fp=fphz; //GBK字库仍有部分汉字缺失,如“镕”字,在字库中不存在
wordOffset=(((long)qm-1)*94+(wm-1))*6; //GBK字库已包含了16区以前的汉字符号字库,计算地址时,区码应减去1,而不是减去6
}
else { //不是GBK字库
if(qm>=16){ //16区以后的汉字
fp=fphz;
wordOffset=(((long)qm-16)*94+(wm-1))*6; //16区以后的汉字偏移
}
else{ //16区以前的汉字符号
fp=fpfh;
wordOffset=(((long)qm-1)*94+(wm-1))*6; //16区以前的汉字符号偏移
}
}
i+=2; //汉字为两字节
}
else{ //是英文字符
fp=fpe;
wordOffset=(0*94+(hzstring[i]-32)-1)*6; //英文字体共有十种0~9,设字体号为N,字符ASCII码为CC,则英文字符偏移为(N*94+(CC-32)-1)*6,空格的ASCII码值为32,但在字库中不存在,字库的起始字符是'!'号,值为33,实际应减33,字库中每种字体字符数为94个
i+=1;
}
fseek(fp,wordOffset,SEEK_SET);
fread(&hz,sizeof(hz_),1,fp);
if(j==1){ //若为汉字,调整地址偏移值
hz.offset-=0x10000000;
j=0;
}
fseek(fp,hz.offset,SEEK_SET);
fread(hzdata,1,hz.length,fp);
while(readcount<hz.length) {
ch=myread(); //取控制码
switch(ch){
case 0: //新起点 0000
if(readcount>0)lineto(bx,by); //整个字的第一个起点时不连接,将笔画的最后一个点与起始点相连,将笔画封闭
xx[0]=readbyte();
yy[0]=readbyte();
xx[0]=xRange*xx[0]/baseSize+0.5;
yy[0]=yRange*yy[0]/baseSize+0.5;
xx[0]+=X0;yy[0]+=Y0;
moveto(xx[0],yy[0]); //笔画起点
curX=xx[0];curY=yy[0];
bx=xx[0];by=yy[0]; //记录笔画的起始点坐标
break;
case 1:
xx[0]=readbyte();
xx[0]=xRange*xx[0]/baseSize+0.5;
xx[0]+=X0;
lineto(xx[0],curY);
curX=xx[0];
break;
case 2:
yy[0]=readbyte();
yy[0]=yRange*yy[0]/baseSize+0.5;
yy[0]+=Y0;
lineto(curX,yy[0]);
curY=yy[0];
break;
case 3:
xx[0]=readbyte();
yy[0]=readbyte();
xx[0]=xRange*xx[0]/baseSize+0.5;
yy[0]=yRange*yy[0]/baseSize+0.5;
xx[0]+=X0;yy[0]+=Y0;
lineto(xx[0],yy[0]);
curX=xx[0];curY=yy[0];
break;
case 4:
xx[0]=curX;yy[0]=curY;
xx[1]=readbyte();
yy[1]=readbyte();
xx[2]=readbyte();
yy[2]=readbyte();
xx[1]=xRange*xx[1]/baseSize+0.5;
yy[1]=yRange*yy[1]/baseSize+0.5;
xx[2]=xRange*xx[2]/baseSize+0.5;
yy[2]=yRange*yy[2]/baseSize+0.5;
xx[1]+=X0;yy[1]+=Y0;
xx[2]+=X0;yy[2]+=Y0;
b3_3(xx,yy,COLOR);
curX=xx[2];curY=yy[2];
moveto(curX,curY);
break;
case 5:
xx[0]=curX;yy[0]=curY;
xx[1]=readbyte();
yy[1]=readbyte();
xx[2]=readbyte();
yy[2]=readbyte();
xx[3]=readbyte();
yy[3]=readbyte();
xx[1]=xRange*xx[1]/baseSize+0.5;
yy[1]=yRange*yy[1]/baseSize+0.5;
xx[2]=xRange*xx[2]/baseSize+0.5;
yy[2]=yRange*yy[2]/baseSize+0.5;
xx[3]=xRange*xx[3]/baseSize+0.5;
yy[3]=yRange*yy[3]/baseSize+0.5;
for(m=1;m<4;m++) {
xx[m]+=X0;yy[m]+=Y0;
}
b3_4(xx,yy,COLOR);
curX=xx[3];curY=yy[3];
moveto(curX,curY);
break;
case 6:
xx[0]=readbyte();
yy[0]=readbyte();
xx[1]=readbyte();
yy[1]=readbyte();
xx[0]=xRange*xx[0]/baseSize+0.5;
yy[0]=yRange*yy[0]/baseSize+0.5;
xx[1]=xRange*xx[1]/baseSize+0.5;
yy[1]=yRange*yy[1]/baseSize+0.5;
for(m=0;m<2;m++) {
xx[m]+=X0;yy[m]+=Y0;
}
rectangle(xx[0],yy[0],xx[1],yy[1]);
break;
case 7:
mark1_x=1;
ch=myread();
if(ch&8)mark1_x=-1;
ch&=7;
xx[0]=curX+ch*mark1_x*xRange/baseSize+0.5;
yy[0]=readbyte();
yy[0]=yRange*yy[0]/baseSize+0.5;
yy[0]+=Y0;
lineto(xx[0],yy[0]);
curX=xx[0];curY=yy[0];
break;
case 8:
mark1_y=1;
xx[0]=readbyte();
xx[0]=xRange*xx[0]/baseSize+0.5;
xx[0]+=X0;
ch=myread();
if(ch&8)mark1_y=-1;
ch&=7;
yy[0]=curY+ch*mark1_y*yRange/baseSize+0.5;
lineto(xx[0],yy[0]);
curX=xx[0];curY=yy[0];
break;
case 9:
mark1_x=1;
mark1_y=1;
ch=myread();
if(ch&8)mark1_x=-1;
ch&=7;
xx[0]=curX+ch*mark1_x*xRange/baseSize+0.5;
ch=myread();
if(ch&8)mark1_y=-1;
ch&=7;
yy[0]=curY+ch*mark1_y*yRange/baseSize+0.5;
lineto(xx[0],yy[0]);
curX=xx[0];curY=yy[0];
break;
case 10:
mark1_x=1;
mark1_y=1;
ch=myread(); //第一次读取的四位作为六位数据的高四位
cha=myread(); //第二次读取的四位的高两位作为六位数据的低两位,低两位作为第二个六位数的高两位
ch=(ch<<2)+(cha>>2);
if(ch&0x20)mark1_x=-1;
ch&=0x1f;
xx[0]=curX+ch*mark1_x*xRange/baseSize+0.5;
ch=myread(); //第三次读取的四位作为第二个六位数的低四位
ch=((cha&0x03)<<4)+ch;
if(ch&0x20)mark1_y=-1;
ch&=0x1f;
yy[0]=curY+ch*mark1_y*yRange/baseSize+0.5;
lineto(xx[0],yy[0]);
curX=xx[0];curY=yy[0];
break;
case 11:
mark1_x=1;
mark1_y=1;
mark2_x=1;
mark2_y=1;
xx[0]=curX;yy[0]=curY;
ch=myread();
if(ch&8)mark1_x=-1;
chx=ch=(ch&7)*mark1_x;
xx[1]=curX+ch*xRange/baseSize+0.5;
ch=myread();
if(ch&8)mark1_y=-1;
chy=ch=(ch&7)*mark1_y;
yy[1]=curY+ch*yRange/baseSize+0.5;
ch=myread();
if(ch&8)mark2_x=-1;
ch=(ch&7)*mark2_x;
xx[2]=curX+(chx+ch)*xRange/baseSize+0.5;
ch=myread();
if(ch&8)mark2_y=-1;
ch=(ch&7)*mark2_y;
yy[2]=curY+(chy+ch)*yRange/baseSize+0.5;
b3_3(xx,yy,COLOR);
curX=xx[2];curY=yy[2];
moveto(curX,curY);
break;
case 12:
mark1_x=1;
mark1_y=1;
mark2_x=1;
mark2_y=1;
xx[0]=curX;yy[0]=curY;
ch=myread(); //1
cha=myread(); //2
ch=(ch<<2)+(cha>>2);
if(ch&0x20)mark1_x=-1;
chx=ch=(ch&0x1f)*mark1_x;
xx[1]=curX+ch*xRange/baseSize+0.5;
ch=myread(); //3
ch=((cha&0x03)<<4)+ch;
if(ch&0x20)mark1_y=-1;
chy=ch=(ch&0x1f)*mark1_y;
yy[1]=curY+ch*yRange/baseSize+0.5;
ch=myread(); //1
cha=myread(); //2
ch=(ch<<2)+(cha>>2);
if(ch&0x20)mark2_x=-1;
ch=(ch&0x1f)*mark2_x;
xx[2]=curX+(chx+ch)*xRange/baseSize+0.5;
ch=myread(); //3
ch=((cha&0x3)<<4)+ch;
if(ch&0x20)mark2_y=-1;
ch=(ch&0x1f)*mark2_y;
yy[2]=curY+(chy+ch)*yRange/baseSize+0.5;
b3_3(xx,yy,COLOR);
curX=xx[2];curY=yy[2];
moveto(curX,curY);
break;
case 13:
mark1_x=1;
mark1_y=1;
mark2_x=1;
mark2_y=1;
mark3_x=1;
mark3_y=1;
xx[0]=curX;yy[0]=curY;
ch=myread();
if(ch&8)mark1_x=-1;
chx=ch=(ch&7)*mark1_x;
xx[1]=curX+ch*xRange/baseSize+0.5;
ch=myread();
if(ch&8)mark1_y=-1;
chy=ch=(ch&7)*mark1_y;
yy[1]=curY+ch*yRange/baseSize+0.5;
ch=myread();
if((ch)&8)mark2_x=-1;
chxx=ch=(ch&7)*mark2_x;
xx[2]=curX+(chx+ch)*xRange/baseSize+0.5;
ch=myread();
if((ch)&8)mark2_y=-1;
chyy=ch=(ch&7)*mark2_y;
yy[2]=curY+(chy+ch)*yRange/baseSize+0.5;
ch=myread();
if((ch)&8)mark3_x=-1;
ch=(ch&7)*mark3_x;
xx[3]=curX+(chx+chxx+ch)*xRange/baseSize+0.5;
ch=myread();
if((ch)&8)mark3_y=-1;
ch=(ch&7)*mark3_y;
yy[3]=curY+(chy+chyy+ch)*yRange/baseSize+0.5;
b3_4(xx,yy,COLOR);
curX=xx[3];curY=yy[3];
moveto(curX,curY);
break;
case 14:
mark1_x=1;
mark1_y=1;
mark2_x=1;
mark2_y=1;
mark3_x=1;
mark3_y=1;
xx[0]=curX;yy[0]=curY;
ch=myread(); //1
cha=myread(); //2
ch=(ch<<2)+(cha>>2);
if(ch&0x20)mark1_x=-1;
chx=ch=(ch&0x1f)*mark1_x;
xx[1]=curX+ch*xRange/baseSize+0.5;
ch=myread(); //3
ch=((cha&0x03)<<4)+ch;
if(ch&0x20)mark1_y=-1;
chy=ch=(ch&0x1f)*mark1_y;
yy[1]=curY+ch*yRange/baseSize+0.5;
ch=myread(); //1
cha=myread(); //2
ch=(ch<<2)+(cha>>2);
if(ch&0x20)mark2_x=-1;
chxx=ch=(ch&0x1f)*mark2_x;
xx[2]=curX+(chx+ch)*xRange/baseSize+0.5;
ch=myread(); //3
ch=((cha&0x03)<<4)+ch;
if(ch&0x20)mark2_y=-1;
chyy=ch=(ch&0x1f)*mark2_y;
yy[2]=curY+(chy+ch)*yRange/baseSize+0.5;
ch=myread(); //1
cha=myread(); //2
ch=(ch<<2)+(cha>>2);
if(ch&0x20)mark3_x=-1;
ch=(ch&0x1f)*mark3_x;
xx[3]=curX+(chx+chxx+ch)*xRange/baseSize+0.5;
ch=myread(); //3
ch=((cha&0x03)<<4)+ch;
if(ch&0x20)mark3_y=-1;
ch=(ch&0x1f)*mark3_y;
yy[3]=curY+(chy+chyy+ch)*yRange/baseSize+0.5;
b3_4(xx,yy,COLOR);
curX=xx[3];curY=yy[3];
moveto(curX,curY);
break;
case 15: //仅读取两个字节,不作处理
readbyte();
readbyte();
break;
}
}
if((readcount<hz.length))lineto(bx,by); //将最后一个笔画的最后一个点与起始点相连,将笔画封闭
getch();
X0+=xRange*168/baseSize+0.5; //此处为168较合适,但未找到原因
if(getmaxx()-X0<xRange*168/baseSize){
X0=0;
Y0+=yRange*168/baseSize+0.5;
}
if(getmaxy()-Y0<yRange*168/baseSize){
Y0=0;
X0=0;
getch();
cleardevice();
}
}
setcolor(oldcolor);
fp=0;
fclose(fpe);
fclose(fpfh);
fclose(fphz);
return;
}
unsigned char myread(void) //每调用一次,读出一个字节的四位数,先读低四位,后读高四位
{
unsigned char a;
if(!next){ //next等于0时读取低四位,为1时读取高四位
a=hzdata[readcount]&0x0f;
next=1;
}
else{
a=(hzdata[readcount]&0xf0)>>4;
readcount++;
next=0;
}
return a;
}
int readbyte(void)
{
int kk=0;
unsigned char a,b;
a=myread()<<4;
b=myread();
kk=(int)(b+a);
return kk;
}
void b3_4(int *x,int *y,unsigned long col) //三次B样条曲线,n可以指定常数
{ int n,*bx,*by,sign=1,j=0,k,i;
double a,b,c,d,dt,xx,f0_3,f_0,f_1,f_2;
n=xx=sqrt(((double)(x[1]-x[0]))*((double)(x[1]-x[0]))+
((double)(y[1]-y[0]))*((double)(y[1]-y[0])))+
sqrt(((double)(x[2]-x[1]))*((double)(x[2]-x[1]))+
((double)(y[2]-y[1]))*((double)(y[2]-y[1])))+
sqrt(((double)(x[3]-x[2]))*((double)(x[3]-x[2]))+
((double)(y[3]-y[2]))*((double)(y[3]-y[2])));
if(xx>n) n++;
n*=2;
if(n==0) n=20;
do {
bx=(int *)malloc(n*sizeof(int));
by=(int *)malloc(n*sizeof(int));
if((!bx)||(!by)) {
/*printf("Memory Alloction Error!");*/
return;
}
dt=(double)1/(double)n;
a=((-1)*x[0]+3*x[1]-3*x[2]+x[3]);
b=3*(x[0]-2*x[1]+x[2]);
c=3*(x[1]-x[0]);
d=x[0];
f0_3=6*a*dt*dt*dt;
f_2=f0_3+2*b*dt*dt;
f_1=f0_3/6+b*dt*dt+c*dt;
f_0=d;
bx[0]=f_0+0.5;
for(i=0;i<n;i++) {
f_0+=f_1;
bx[i]=f_0+0.5;
f_1+=f_2;
f_2+=f0_3;
}
a=((-1)*y[0]+3*y[1]-3*y[2]+y[3]);
b=3*(y[0]-2*y[1]+y[2]);
c=3*(y[1]-y[0]);
d=y[0];
f0_3=6*a*dt*dt*dt;
f_2=f0_3+2*b*dt*dt;
f_1=f0_3/6+b*dt*dt+c*dt;
f_0=d;
bx[0]=f_0+0.5;
for(i=0;i<n;i++) {
f_0+=f_1;
by[i]=f_0+0.5;
f_1+=f_2;
f_2+=f0_3;
}
sign=1;j=0;k=n/100+1;
for(i=1;i<n;i++) {
if((abs(bx[i]-bx[i-1])>1)||(abs(by[i]-by[i-1])>1)) j++;
if(j>k) {
free(bx); free(by);
if(n>3) n=n+n/3;
else n=6;
sign=0;
} break;
}
} while(sign==0);
for(i=1;i<n;i++)
if((bx[i]!=bx[i-1])||(by[i]!=by[i-1])) putpixel(bx[i],by[i],col);
free(bx); free(by);
}
void b3_3(int *x,int *y,unsigned long col) //二次B样条曲线,n可以指定常数
{ int n,*bx,*by,sign=1,j=0,k,i;
double a,b,c,d,dt,xx,f0_3,f_0,f_1,f_2;
n=xx=sqrt(((double)(x[1]-x[0]))*((double)(x[1]-x[0]))+
((double)(y[1]-y[0]))*((double)(y[1]-y[0])))+
sqrt(((double)(x[2]-x[1]))*((double)(x[2]-x[1]))+
((double)(y[2]-y[1]))*((double)(y[2]-y[1])));
if(xx>n) n++;
n*=4;
if(n==0) n=20;
do {
bx=(int *)malloc(n*sizeof(int));
by=(int *)malloc(n*sizeof(int));
if((!bx)||(!by)) {
/*printf("Memory Alloction Error!");*/
return;
}
dt=(double)1/(double)n;
b=x[0]-2*x[1]+x[2];
c=2*(x[1]-x[0]);
d=x[0];
f_2=2*b*dt*dt;
f_1=b*dt*dt+c*dt;
f_0=d;
bx[0]=f_0+0.5;
for(i=0;i<n;i++) {
f_0+=f_1;
bx[i]=f_0+0.5;
f_1+=f_2;
}
b=y[0]-2*y[1]+y[2];
c=2*(y[1]-y[0]);
d=y[0];
f_2=2*b*dt*dt;
f_1=b*dt*dt+c*dt;
f_0=d;
by[0]=f_0+0.5;
for(i=0;i<n;i++) {
f_0+=f_1;
by[i]=f_0+0.5;
f_1+=f_2;
}
sign=1;j=0;k=n/100+1;
for(i=1;i<n;i++) {
if((abs(bx[i]-bx[i-1])>1)||(abs(by[i]-by[i-1])>1)) j++;
if(j>k) {
free(bx); free(by);
if(n>3) n=n+n/3;
else n=6;
sign=0;
} break;
}
} while(sign==0);
for(i=1;i<n;i++)
if((bx[i]!=bx[i-1])||(by[i]!=by[i-1]))
{
putpixel(bx[i],by[i],col);
}
free(bx); free(by);
}
|