最近由于工作原因一直在编写热敏打印应用相关的代码,其中就涉及到中文打印。对于中文打印大概涉及三个方面的内容:中文输入、汉字编码与转码、点阵字体的处理。对于这三个方面涉及的知识还是挺多的,在此就对点阵字体相关的内容做一个小结。
一、点阵字体概述
做过单片机点阵开发的同学肯定不会陌生,对于16x16的点阵,当某些位点亮某些位熄灭时就可以显示文字或图片。对于点阵字体其实就是将这些位的亮灭信息保存在一个数组里,将所有字的这些信息都这样存储起来就形成了一个字库文件。根据保存信息的不同形成不同的字库,如HZK16,HZK24,HZK32。
如下HZK16单个字的存储:
const unsigned char acFontHZKaiTi_16_b0de[32] = {
________,_X______,
_____X__,_X______,
____XX__,X_XXX___,
__XXX__X,XX__X___,
____X__X,_XX_X___,
___XXX_X,_X__X___,
XXX_X__X,XXXX____,
___XX___,X_X_____,
__X_XX__,X_XXXXX_,
__X_X_XX,XXX_____,
_X__X___,__X_____,
X___X___,__X_____,
____X___,__X_____,
____X___,__X_____,
________,__X_____,
________,________,
};
二、点阵字体的显示
点阵字体的显示比较简单,只需将每个字节信息中的每一位按需求显示或不显示就行了,直接上代码(以HZK16为例):
static VOID PrintHzk16Font(UINT8* fontDat)
{
INT i, j, b;
UINT8 byte;
if (fontDat != NULL)
{
for (i = 0; i < 16; i++)
{
for (j = 0; j < 2; j++)
{
byte = fontDat[i*2 + j];
for (b = 7; b >=0; b--)
{
if (byte & (1< {
printf("*"); //show
}
else
{
printf(" "); //hide
}
}
}
printf("\n");
}
}
}
三、点阵字体的旋转
点阵字体的旋转其实就是取出数组中的某个元素的某一位保存在数组中的另外某个元素中的某一位中,根据旋转方式的不同读取和保存的方式都不一样。在此以HZK16字体旋转为例:
#define GET_BIT(src, n) ((src) & (0x01 << (n)))
#define SET_BIT(dst, n) ((dst) |= (0x01 << (n)))
/*
第一列 第二列
________, ________,
______XX, XXXXXX__,
XXXXX_XX, XXXXXX__,
XXXXX_XX, _XX_XX__,
__XX__XX, XXXXXX__,
__XX__XX, _XX_XX__,
XXXXX_XX, _XX_XX__,
XXXXX_XX, XXXXXX__,
前八个字节
__XX__XX, XXXXXX__,
__XX____, _XX_____,
__XX____, _XX_____,
__XXX_XX, XXXXXX__,
XXXXX___, _XX_____,
XX___XXX, XXXXXXX_,
_____XXX, XXXXXXX_,
________,________,
后八个字节
划分为四块,然后一块一块的处理
*/
static VOID RotateHzk16Font(UINT8* dst, UINT8* src)
{
int i, j;
if (NULL == src || NULL == dst)
{
e_WARN("src is null.\n");
return;
}
bzero(dst, FONT16X16_BUF);
//第一列后8个字节
for (i = 0; i < 8; ++i)
{
for (j = 0; j < 8; ++j)
{
if (GET_BIT(src[16+j*2], 7-i))
{
SET_BIT(dst[i*2], j);
}
}
}
//第一列前8个字节
for (i = 0; i < 8; ++i)
{
for (j = 0; j < 8; ++j)
{
if (GET_BIT(src[j*2], 7-i))
{
SET_BIT(dst[1+i*2], j);
}
}
}
//第二列后8个字节
for (i = 0; i < 8; ++i)
{
for (j = 0; j < 8; ++j)
{
if (GET_BIT(src[17+j*2], 7-i))
{
SET_BIT(dst[16+i*2], j);
}
}
}
//第一列前8个字节
for (i = 0; i < 8; ++i)
{
for (j = 0; j < 8; ++j)
{
if (GET_BIT(src[1+j*2], 7-i))
{
SET_BIT(dst[17+i*2], j);
}
}
}
}
其实对于字体的旋转可以写一个通用的算法适合任何字体的旋转,在此就不具体实现了。大概的思路是:根据字体的大小确定旋转后的空间大小,注意如果字体的宽高不一样的话旋转后的空间可能会大于原字体的存储空间,然后八个字节八个字节的批量处理。