字符的点阵显示原理及实现字符的点阵显示原理及实现 武汉大学遥感信息工程学院,屈伟军 首先介绍什么是点阵字库需要理解的是,点阵字库是一个数据文件,在这个数据文件里 面保存了所有字符的点阵数据至于什么是点阵,我想大家都知道如果使用过“文曲星”之 类的电子辞典,在那个液晶显示屏上就可以明显地看出“点阵”的痕迹所在PC 机上也是如 此,字符是由点阵来组成的,不同的是 PC 机显示器的显示分辨率更高,高到了我们肉眼无法 区分的地步,因此“点阵”的痕迹也就不那么明显了点阵从本质上讲就是单色位图,它使用 一个比特位来表示一个点,如果某个比特位为 0,表示该位置没有点,如果为 1 则表示该位置 有点那么点阵字符的数据存放细节到底是怎么样的呢?其实十分简单,举个例子最能说明问 题比如说 16×16 的字符点阵,一行有 16 个点,需要用 16 个比特即 2 个字节来存放第一行 的前八个点的数据存放在点阵数据的第一个字节里面, 第一行的后面八个点的数据存放在点阵 数据的第二个字节里面, 第二行的前八个点的数据存放在点阵数据的第三个字节里面……以此 类推一个点阵共有 16 行,这样我们马上就可以计算出存放一个点阵总共需要 2×16 = 32 个 字节。
看看下面这个图形化的例子: 0000000100000000000000000000010000000 0000000001010001010101010101010100000 0000000000010000000000000000010000000 0000010000000000010000000000010000000 0000000101000000010000000000010000000 0000000001000000010000000001000000000 0000000000000100000100000001000000000 0000000000010000000100000100000000000 0000000001000000000001000100000000000 0000010101000000000000010000000000000 0000000001000000000001000100000000000 0000000001000000000100000001000000000 0000000001000000010000000000010000000 0000000001000001000000000000010101000 0000000000000100000000000000000100000 0000000000000000000000000000000000000 可以看出这是一个宋体 “汉” 字的点阵, 我们可以写出这个点阵的点阵数据是: 0x40, 0x08, 0x37,0xfc,0x10,0x08……当然,写这个确实很麻烦,所以我不再继续下去。
我这样做,只 是为了说明在点阵字库中,每一个点阵的数据就是按照这种方式存放的 当然也存在着不规则的点阵,这里说的不规则,指的是点阵的宽度不是 8 的倍数,比如 12×12 的点阵(如图 2 所示) 那么这样的点阵数据又是如何存放的呢?其实也很简单,每一 行的前面8个点存放在一个字节里面, 每一行剩下的4个点也使用一个字节来存放 也就是说, 剩下的 4 个点将占用一个字节的高 4 位,而这个字节的低 4 位没有使用,全部都为 0这样做 当然显得有点浪费,不过却能够便于我们进行存放和寻址对于其他不规则的点阵,也是按照 这个原则进行处理的这样我们可以得出一个 M×N 的点阵所占用的字节数为(M+7)/8×N 图 1 字符“我”的 12×12 点阵 在明白了点阵字符的存放结构以后, 我们很容易就可以写出一个显示任意大小的点阵字符 的函数接下来的问题就是如何在汉字库中寻址某个汉字的点阵数据要解决这个问题,首先 需要了解汉字在计算机中是如何表示的 在计算机中英文可以使用 ASCII 码来表示, 而汉字使 用的是扩展 ASCII 码所谓扩展 ASCII 码,也就是把 ASCII 码的最高位由 0 变为 1 的 ASCII 码,简单的说就是码值大于等于 128 的 ASCII 码。
一个汉字由两个扩展 ASCII 码组成,第一 个扩展 ASCII 码用来存放区码,第二个扩展 ASCII 码用来存放位码在 GB2312-80 标准中, 将所有的汉字分为 94 个区, 每个区有 94 个位可以存放 94 个汉字, 形成了人们常说的区位码, 这样总共就有 94×94 = 8836 个汉字在点阵字库中,汉字点阵数据就是按照这个区位的顺序 来存放的,也就是最先存放的是第一个区的汉字点阵数据,在每一个区中又是按照位的顺序来 存放的在汉字的机内码中,汉字区位码的存放是在扩展 ASCII 码的基础上进行的,存放时将 区码和位码都加上了 32,然后分别存放在两个扩展 ASCII 码中具体的说就是: 第一个扩展 ASCII 码 = 128+32+汉字区码 第二个扩展 ASCII 吗 = 128+32+汉字位码 如果用 char hz[2]来表示一个汉字,那么可以计算出这个汉字的区位码为: 区码 = hz[0]-128-32 = hz[0]-160 位码 = hz[1]-128-32 = hz[1]-160 这样,我们就可以根据区位码在文件中进行寻址了,寻址公式如下: 汉字点阵数据在字库文件中的偏移 = ((区码-1)×94+位码)×一个点阵字符占用的字节数 在寻址以后,便可读取汉字的点阵数据到缓冲区进行显示了。
以上介绍完了中文点阵字库的原理,当然还有英文点阵字库英文点阵字库中单个点阵字 符数据的存放方式与中文是一模一样的,唯一不同的是在对点阵字库的寻址上,英文使用的是 ASCII 码,其码值是 0 到 127,寻址公式为: 英文点阵数据在英文点阵字库中的偏移 = 英文的 ASCII 码×一个英文字符占用的字节数 可以看到, 区分中英文的关键就是, 一个字符是 ASCII 码还是扩展 ASCII 码, 如果是 ASCII 码,其小于 128,则使用的是英文字库,如果是扩展 ASCII 码,其大于等于 128,则与其后面 的另一个扩展 ASCII 码组成汉字内码,使用中文字库进行显示只要正确区分 ASCII 码的类 型并进行分别的处理,也就能实现中英文字符串的混合输出了 下面给出字符点阵输出的一个例子: ■ ■■■■ ■■■ ■ ■■ ■■ ■ ■■■ ■■ ■■ ■ ■■ ■ ■■■ ■■ ■■■ ■■ ■■ ■■■■ ■■ ■■ ■ ■■■ ■■■■■ ■■■ ■■ ■■■■■ ■■ ■■ ■■■■ ■■■■■■ ■■ ■■■■■■ ■■■■■■ ■■ ■■■■■■■ ■■■■■ ■■■ ■■■■ ■■ ■■■■■■■ ■■■■■■■ ■■■ ■■ ■■■ ■ ■ ■■ ■■■■■■ ■■■■■■■ ■■■■ ■■ ■■■■■ ■ ■ ■■ ■■■■■ ■■ ■■ ■■■ ■■■■■■ ■ ■■ ■■■■■■■■■ ■■■■■■ ■ ■ ■■■■■■ ■■■■■ ■■ ■ ■ ■■■■■ ■■■■■■ ■■■ ■■ ■■ ■■■■ ■■■ ■ ■ ■■■■■ ■■■■ ■■ ■ ■■ ■■■■■ ■■■ ■ ■ ■■ ■■■■■■■■ ■■ ■■ ■■■■ ■■■ ■■■ ■ ■■ ■ ■ ■■■ ■■■ ■■■■ ■■■■■■■■■ ■ ■■■■■■■ ■ ■ ■■ ■ ■ ■ ■■ ■■■ ■■■ ■■ ■■■■■ ■■■■ ■■■ ■ ■■■ ■■ ■ ■■ ■ ■ ■■■ ■■■■ ■ ■■ ■■■■■ ■ ■ ■■ ■■■■■ ■■■ ■ ■ ■■ ■■■ ■ ■■ ■ ■■ ■■ ■■■■■ ■■ ■■■ ■ ■■ ■ ■■ ■■■ ■■■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■■ ■■ ■ ■ ■■■■ ■■ ■■■ ■ ■ ■ ■ ■ ■ ■■■■■■ ■ ■ ■■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■■■■ ■ ■ ■■ ■■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■■ ■ ■ ■ ■ ■ ■ ■ ■ ■■■ ■■■■■ ■■■ ■■■■■■■■■ ■■■ ■■■ ■■■ ■■ ■■ ■ ■ ■■ ■■ ■ ■ ■ ■ ■ ■ ■ ■ ■■ ■■■ ■■■ ■■■ ■■■ ■■■■ ■■■ ■■■ ■■■■■ ■■■ ■■■■■ ■■■ ■■■ ■ ■ ■■ ■ ■ ■ ■ ■ ■ ■■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■■■■■■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■■■■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■■ ■■■■ ■■■ ■■■ ■■■■■ ■ ■■■■ ■■■■■ ■■■■■ ■■■■■ ■■ ■ ■ ■■■ 。