我们要在LCD上显示一个字符,首先得取得这个字的字模,也就是点阵,但是怎样在一个字库里面取的我们想要显示的字的点阵数据呢,也就是怎样取得要显示的字的偏移地址。
在开始讲怎样取得汉字的偏移地址前,先讲述一下怎样在内存中表示一个汉字的点阵,如果系统所使用的“汉字库”中每个汉字按16x16点阵模式存放,则每个汉字由16x16=256个点组成,占用16x2=32个字节的连续内存单元。每个字节有8位,每一位都有两种状态,即亮或暗,分别用1或0来表示。在16x16点阵中,用各个位的亮暗来表示一个字,凡是笔画经过的地方都为1(亮),没有笔画的地方都为0(暗),这样就可以表示不同的汉字。
举个例子:"啊"字可以表示为
U8 acFontHZ16x16_b0a1[] =
{
________,________,
XXXXXXXX,XXXXXXXX,
XX_XXXXX,X____XX_,
XX_XXXXX,X____XX_,
XX_XXXXX,_XXXXXX_,
XX_XXXXX,_XXXXXX_,
XX_XXXXX,XXXXXXX_,
XX_XXXXX,XXXXXXX_,
XX_XXXXX,XXXXXXX_,
XXXXXXXX,XXXXXXX_,
XX_XXXXX,XXXXXXX_,
_____XX_,_____XX_,
_____XX_,_____XX_,
_____XX_,_____XX_,
_____XX_,___XXXX_,
_____XX_,____XX__,
};
好,现在我们再了解一下汉字区位码等...
相信写过汉字显示的朋友都非常熟悉这样一个公式:
偏移地址 = [(0xAB-0xA1)X94+(0xCD-0xA1)]X32
但也许有刚开始接触的朋友并不了解为什么这样能算出某个字的偏移地址来...(都知道的朋友别骂我在写这么简单的东西哦)
这里先说明一下GB2312中涉及到的几个概念:区位码、国标码、内码。
中文国标字符集是一个94×94的矩阵,其中每一个汉字(包括数字、英文字母和标点符号)都是二维矩阵中的某个元素。这样,每一个汉字都可以用一个二元组来表示(x,y)。其中,x是该字所在的行号,y为列号。
GB2312在此基础上对矩阵进行划分,分为94个区,每区94位,x定义了该字所在的行号,y表示该字所在的位号,x和y均以二进制或十六进制表示。这就是“区位码”,例如:“啊”字的区位码为(0x10,0x01),表示位于16区第一位。于是汉字库中的字模存放位置(相对于字库文件头的偏移地址)可以由区位码计算得到:偏移地址=区码×94+位码。那么“啊”字的字模相对于字库文件头的偏移地址等于16×94+1=1505(十进制表示)。
但是许多低位数字已被其它领域所占用,比如:0x06表示通信确认回答标志。为了不与已经存在的信码相混淆,GB2312在每个区位码上加上0x20,这样形成的码叫国标码。例如:“啊”字的国标码为(0x30,0x21)。
由于通用的ASCII字符的最高位为0,为了在计算机内部和之间传输汉字时可以和ASCII码区别开来,将表示汉字的两个字节的最高位都置1。这样,相当于在国标码基础上高低字节同时加了0x80,这就是上面提到的内码。比如:“啊”字的内码为(0xB0,0xA1)。在计算机内部,用内码来唯一标识一个汉字。在程序中,通过调用系统函数取得某个汉字的ASCII字符表示,也就得到了这个汉字的内码。
在明白了内码和区位码之间的关系后,我们可以根据某个汉字的内码计算得到该汉字的区位码;再通过区位码计算得到该汉字的字模在汉字库表中的偏移地址;从此地址开始的连续32个字节就是该汉字的字模信息。
那么我们现在知道,如果我们用到的字库是16X16的,那么"啊"的偏移地址就是:
偏移地址 = [(0xB0-0xA1)X94+(0xA1-0xA1)]X32.