在做M4中文显示的时候,突然想到是否可以在Ti的官方图形库里面直接添加中文显示的支持呢?于是我在论坛里搜索了一下!发现原来早有大神实现了这个想法:
基于汉字字模的Stellaris+GUI控件驱动设计.PDF
(513.57 KB, 下载次数: 107)
方法成功后,我发现了一个问题,那就是怎样在一个画布栏里同时显示中文和英文字符呢?
在画布显示英文官方例程里比比皆是,像这样:
可以看到&g_sFontCm20是官方提供的字库,它是不支持中文的,而当我使用上面描述的方法时,就只会支持显示中文了,所以我在种方法上进行了改进,它的处理程序会变成:
好了,接下来我具体说说改进的地方:
1、首先我用汉字取模工具批量取模了常用的3500个汉字和常用的英文字符。
当然如果你觉得有点大的话,可以自己精简的,我主要是为了可以随心所欲的显示基本的汉字语句才取得这么多的汉字!
grlib.h基本上按照前面pdf所说的那样改进,我把这个结构体
//***********汉字字模的数据结构定义***********//
typedef struct //汉字字模数据结构
{
unsigned char Index[3]; //汉字内码索引
const unsigned char *Msk; //点阵数据指
}typ_CHFont;
中的汉字内码索引和点阵数据指位置互换了一下!还有就是结构体tFont中的
//The offset within pucData to the data for each ASCII character in the font. Or
//pusOffset[0] is the number of Chinese Font that stored in CHFontdata when the
//Chinese Font is selected.
unsigned long pusOffset[96];
我这里把原来的short型换了long,具体原因在第二点有说明。
2、然后我建立了fontCH16.c文件,这里字库的数量和种类增加了,结构体g_sFontCH16中的 {3685}对应着字符的个数,原来的short型会溢出,所以改为long型,对应的String.c也要做出修改!
3、接着是对string.c的修改:
能够不光显示中文,还要显示英文的关键就在这里!
我们知道,汉字的内码占两个字节,所以显示程序的处理程序为:
width=sCon.pFont->ucMaxWidth;
if(sCon.pFont->ucHeight%8 == 0)
{
Colum = sCon.pFont->ucHeight/8;
EndNum = 0;
} else
{
Colum = (sCon.pFont->ucHeight/8)+1;
EndNum = sCon.pFont->ucHeight%8;
}
for(CHFontNum=0;CHFontNum<sCon.pFont->pusOffset[0];CHFontNum++)
{
if((sCon.pFont->CHFontdata[CHFontNum].Index[0]==pcString[0])&&
(sCon.pFont->CHFontdata[CHFontNum].Index[1]==pcString[1])) //这里是关键,利用汉字两个字节的内码索引汉字!
{
for(m=0; m<Colum; m++)
{
for(i=0; i<width; i++)
{
if(sCon.pFont->CHFontdata[CHFontNum].Msk[i+m*width]>0)
{
lIdx=1;
lBit=0;
if(m!=Colum-1 || EndNum==0)
{
while(lBit<9)
{
if(sCon.pFont->CHFontdata[CHFontNum].Msk
[i+m*width]&lIdx)
{
GrPixelDraw(&sCon,lX+i,lY+lBit+8*m);
}
lIdx=lIdx<<1;
lBit++;
}
}
}
else
{
if(EndNum!=0)
{
while(lBit!=EndNum+1)
{
if(sCon.pFont->CHFontdata[CHFontNum].Msk[i+m*width]&lIdx)
{
GrPixelDraw(&sCon,lX+i,lY+lBit+8*m);
}
lIdx=lIdx<<1;
lBit++;
}
}
}
}
}
}
}
lX=lX+width;
pcString+=2;//因为占两个字节,所以每次循环要加2!
}
接下来问题来了,英文字符的ASCII码(内码)只占一个字节,要是还按照此种方法的话,那么它是不能正常显示的,它的内码回和案子内码相混淆,导致两者不能同时正常显示!好在汉字和英文字符内码有着本质的区别,汉字内码的最高为为1,而英文字符的内码最高为为0,所以我们能够用
if(pcString[0]<=127)//区别英文内码和中文内码
语句来判断是否要显示是英文字符!
接下就是我取得英文字符宽度为8,所以 width=(sCon.pFont->ucMaxWidth)/2;//英文字符宽度为8!
然后就是只判断:
if((sCon.pFont->CHFontdata[CHFontNum].Index[0]==pcString[0]))
最后还要记得pcString+=1;
好了这样string.c就修改完了!
4、接下来就是在主程序里调用此字库了!
另外例程里的grlib.a已经被我更新了!所以直接添加的驱动库!
图片:
测试视频: