JavaME UI设计之点阵字体

 
上一篇文章中我们介绍了在JavaME中实现Bitmap字体,但是要想通过Bitmap字体来显示中文几乎不太可能,除非你中文很少,也不介意这样做浪费时间,如果你想显示中文,又不想使用JavaME本身提供的字体,那么可以考虑使用点阵字,这就是本文将要给大家介绍的,如何在JavaME中使用点阵字库。
要在JavaME中使用点阵字,首先需要了解什么是点阵字,可以到各大百科互动网站找到相关介绍,这里就不耽误大家的时间了,点阵字实际上就是用画点的方式画出一个字。比如一个16*16的点阵字,它的每一个点占一位,一共是16*16,那么一个16的字所占大小是32byte。需要明白点阵字体优点是显示速度快,不像矢量字体需要计算;其最大的缺点是不能放大,一旦放大后就会发现文字边缘的锯齿,因此如果需要显示不同大小的点阵字,就需要准备不同大小的点阵字库。
点阵字库的制作方法也非常简单,网上有很多方法,本文我们选择使用HZK16字库来演示在JavaME如何使用点阵字库。
HZK16字库是符合GB2312标准的16× 16点阵字库,HZK16的GB2312-80支持的汉字有6763个,符号682个。其中一级汉字有3755个,按声序排列,二级汉字有3008个,按偏旁部首排列。我们在一些应用场合根本用不到这么多汉字字模,所以在应用时就可以只提取部分字体作为己用。HZK16字库里的16×16汉字一共需要256个点来显示,也就是说需要32个字节才能达到显示一个普通汉字的目的。 我们知道一个GB2312汉字是由两个字节编码的,范围为A1A1~FEFE。A1-A9为符号区,B0到F7为汉字区。每一个区有94个字符(注意:这只是编码的许可范围,不一定都有字型对应,比如符号区就有很多编码空白区域)。下面以汉字“我”为例,介绍如何在HZK16文件中找到它对应的32个字节的字模数据。前面说到一个汉字占两个字节,这两个中前一个字节为该汉字的区号,后一个字节为该字的位号。其中,每个区记录94个汉字,位号为该字在该区中的位置。所以要找到“我”在hzk16库中的位置就必须得到它的区码和位码。
区码:区号(汉字的第一个字节)-0xa0(因为汉字编码是从0xa0区开始的,所以文件最前面就是从0xa0区开始,要算出相对区码)
位码:位号(汉字的第二个字节)-0xa0
这样我们就可以得到汉字在HZK16中的绝对偏移位置:
offset=(94*(区码-1)+(位码-1))*32
有了偏移地址就可以从HZK16中读取汉字编码了,下面我们就需要在JavaME中构建一个能够读取和显示点阵字库文字的类CustomFont,首先将我们准备的点阵字库HZK16放入工程的res文件夹中,并在CustomFont中标出该字库的路径和编码的等信息,如下代码所示。
public class CustomFont {
       public final static int[] mask = { 128, 64, 32, 16, 8, 4, 2, 1 };
       public final static String ZK_PATH = "/HZK16";
       public final static String ENCODE = "GB2312";
       //...
}
要读取一个汉字,我们首先要读取出汉字的区位码,通过如下代码可以读取出汉字的区位码:
/**
 *获得文字的区位码
 */
protected int[] getByteCode(String str) {
       int[] byteCode = new int[2];
       try {
              byte[] data = str.getBytes(ENCODE);
              byteCode[0] = data[0] < 0 ? 256 + data[0] : data[0];
              byteCode[1] = data[1] < 0 ? 256 + data[1] : data[1];
       } catch (Exception ex) {
       }
       return byteCode;
}
然后通过区位码在字库中去查找文字信息,具体实现代码如下:
/**
 *读取文字信息
 *
 * @param areaCode
 *            区码
 *@param posCode
 *             位码
 *@return 文字数据
 */
protected byte[] read(int areaCode, int posCode) {
       byte[] data = null;
       try {
              int area = areaCode - 0xa0;// 获得真实区码
              int pos = posCode - 0xa0;// 获得真实位码
 
              InputStream in = getClass().getResourceAsStream(ZK_PATH);
              long offset = 32 * ((area - 1) * 94 + pos - 1);
              in.skip(offset);
              data = new byte[32];
              in.read(data, 0, 32);
              in.close();
       } catch (Exception ex) {
       }
       return data;
}
能从字库中读取出点阵字的信息,下面就是将这些数据绘制出来即可,绘制函数如下所示。
/**
 *绘制点阵中文汉字,gb2312,16字
 *
 * @param g
 *             画笔
 *@param str
 *             需要绘制的文字
 *@param x
 *             屏幕显示位置x
 *@param y
 *             屏幕显示位置y
 *@param color
 *             文字颜色
 *
 */
protected void drawString(Graphics g, String str, int x, int y, int color) {
       byte[] data = null;
       int[] code = null;
       int byteCount;// 到点阵数据的第几个字节了
       int lCount;// 控制列
       g.setColor(color);
       for (int i = 0; i < str.length(); i++) {
              if (str.charAt(i) < 0x80) {// 非中文
                     g.drawString(str.substring(i, i + 1), x + (i << 4), y, 0);
                     continue;
              }
              code = getByteCode(str.substring(i, i + 1));
              data = read(code[0], code[1]);
              byteCount = 0;
              for (int line = 0; line < 16; line++) {
              lCount = 0;
              for (int k = 0; k < 2; k++) {
                     for (int j = 0; j < 8; j++) {
                            if ((data[byteCount] & mask[j]) == mask[j]) {
                                   g.drawLine(x + lCount + (i << 4), y + line, x
                                   + lCount + (i << 4), y + line);
                            }
                     lCount++;
                     }
                     byteCount++;
              }
       }
}
完成了点阵字的读取和绘制操作,下面我们通过:
mCustomFont.drawString(g, "测试点阵字库的显示!好看多了。", 0, 20, 0xff0000);
来测试该自定义点阵字库在JavaME中的使用 ,效果如下图所示。
 

 
显示肯定没有问题,但是我们开发出来的应用程序包也就随之增加了很大,主要包括HZK16字库文件,另外,在使用过程中所需要消耗的内存也增加,因为一个16*16的汉字就需要32个字节,因此,对于应用中汉字较少的,可以采用自己制作出一些特定的点阵字的数组,然后进行绘制,可以节省不少空间。
关于JavaME中字体的处理就介绍到这里,几乎介绍了JavaME中所有与字体相关的内容,足以解决JavaME中大部分文字显示的难题了。


你可能感兴趣的:(JavaME UI设计之点阵字体)