首先说说基本知识:
1、HZK16字库是符合GB2312标准的16×16点阵字库,HZK16的GB2312-80支持的汉字有6763个,符号682个。其中一级汉字有 3755个,按声序排列,二级汉字有3008个,按偏旁部首排列。
这就是说,我们要完成这个程序,需要一个点阵字库文件:HZK16,自行百度搜索~
HZK16字库里的16×16汉字一共需要256个点来显示,也就是说需要32个字节才能达到显示一个普通汉字的目的。
我们知道一个GB2312汉字是由两个字节编码的,范围为0xA1A1~0xFEFE。A1-A9为符号区,B0-F7为汉字区。每一个区有94个字符(注意:这只是编码的许可范围,不一定都有字型对应,比如符号区就有很多编码空白区域)。
下面以汉字”我”为例,介绍如何在HZK16文件中找到它对应的32个字节的字模数据。
前面说到一个汉字占两个字节,这两个中前一个字节为该汉字的区号,后一个字节为该字的位号。其中,每个区记录94个汉字,位号为该字在该区中的位置。所以要找到”我”在hzk16库中的位置就必须得到它的区码和位码。
区码:汉字的第一个字节-0xA0 (因为汉字编码是从0xA0区开始的, 所以文件最前面就是从0xA0区开始, 要算出相对区码)
位码:汉字的第二个字节-0xA0
这样我们就可以得到汉字在HZK16中的绝对偏移位置:
offset=(94*(区码-1)+(位码-1))*32
2、输出流收到一个换行符才将缓冲区中的内容输出,因此程序中仅有System.out.print(” “)语句是不会输出的,必须有System.out.println()。
附上关键代码:
package com.example.rabbit.fontshow;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.io.InputStream;
public class MainActivity extends AppCompatActivity {
boolean[][] arr;
int all_16_32 = 16;
int all_2_4 = 2;
int all_32_128 = 32;
public boolean[][] drawString(String str) {
byte[] data = null;
int[] code = null;
int byteCount;
int lCount;
arr = new boolean[all_16_32][all_16_32];
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) < 0x80) {
continue;
}
code = getByteCode(str.substring(i, i + 1));
data = read(code[0], code[1]);
byteCount = 0;
for (int line = 0; line < all_16_32; line++) {
lCount = 0;
for (int k = 0; k < all_2_4; k++) {
for (int j = 0; j < 8; j++) {
if (((data[byteCount] >> (7 - j)) & 0x1) == 1) {
arr[line][lCount] = true;
System.out.print("*");
} else {
System.out.print(" ");
arr[line][lCount] = false;
}
lCount++;
}
byteCount++;
}
System.out.println();
}
}
return arr;
}
protected byte[] read(int areaCode, int posCode) {
byte[] data = null;
try {
int area = areaCode - 0xa0;
int pos = posCode - 0xa0;
InputStream in = getResources().openRawResource(R.raw.hzk16);
long offset = all_32_128 * ((area - 1) * 94 + pos - 1);
in.skip(offset);
data = new byte[all_32_128];
in.read(data, 0, all_32_128);
in.close();
} catch (Exception ex) {
System.err.println("SORRY,THE FILE CAN'T BE READ");
}
return data;
}
protected int[] getByteCode(String str) {
int[] byteCode = new int[2];
try {
byte[] data = str.getBytes("GB2312");
byteCode[0] = data[0] < 0 ? 256 + data[0] : data[0];
byteCode[1] = data[1] < 0 ? 256 + data[1] : data[1];
} catch (Exception ex) {
ex.printStackTrace();
}
return byteCode;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
drawString("胡萝卜");
}
}