点阵字体显示系列补记2:关于24点阵汉字显示程序及其修改版本
自从写完16点阵后,由于没啥事做,就继续看看24点阵是如何显示的。这种规格的点阵是使用UCDOS(虽然下载了,但用不了)中的汉字字库。又千辛万苦找到ASCII码的24点阵,再修改前面的程序,生成24点阵ASCII码的数组。测试完后,用一天时间,在触摸屏搞出了汉字显示,不过对比了Tslib库的代码,发觉自己写的简直是一塌糊涂,于是继续修改代码。不过,由于不知道如何优化代码及组织代码结构,修改后的成果仅仅是生成的可执行文件大小比原来的版本少240个字节(使用size命令查看得到的结果)。这也算是一个进步吧,网络上关于专门针对某种平台、某种情景的代码优化资料比较少,靠以前和平时一点一点积累,实属不易。
在这里贴上两个版本的源代码,估计没啥人研究这玩意,因此程序不作解释。在不影响代码功能及坚持本人代码风格前提下,尽量减少不必要的行数,对代码中的笔误及其它不影响功能的小毛病,恕不再作修改。
原来的版本:
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <ncurses.h> /* ncurses库头文件 */#include “ascii24.h”
#define ascii_code ascii24
/* for debug */
//#define DEBUG
#ifdef DEBUG
#define debug(fmt, …) printw(fmt, ##__VA_ARGS__)
#else
#define debug(fmt, …)
#endif
#define size 24 /* 点阵规格:24点阵 */
#define bytes (size/8) /* 汉字占用字节:3字节,即分3次取数据 */
#define buf_size (bytes * size) /* 汉字缓冲区大小:3*24 = 72字节 */
#define ascii_bytes (bytes-1) /* 24点阵ASCII码占用字节:2字节,即分2次取数据,与16点阵汉字一样*/
#define ascii_size (size * ascii_bytes) /* ASCII缓冲区大小:24*2 = 48字节 */
/*
使用UCDOS汉字库显示汉字,需转置
y:行
x:列
mat:二维数组
code:显示的字符(如”*”等)
*/
static void __display_font(int y, int x, unsigned char mat[][3], char *code)
{
int i, j;
for(i=0;i<size;i++)
for(j=0;j<size;j++)
if(mat[j][i/8] & (0x80>>i%8))
mvprintw(y+i, x+j, code);
else
mvprintw(y+i, x+j, ” “);
refresh();
}
static void __display_ascii(int y, int x, unsigned char *mat, char *code)
{
int i, j, k;
for(i=0;i<size;i++)
for(j=0;j<ascii_bytes;j++)
for(k=0;k<8;k++)
/* 从高位开始,逐位相与,为1者,输出“*” */
if(mat[i*ascii_bytes+j] & (0x80>>k))
mvprintw(y+i, x+j*8+k, code);
else
mvprintw(y+i, x+j*8+k, ” “);
refresh();
}
/*
* 打印ASCII,使用96个可打印字符版本的ASCII码数组
* y:屏幕行
* x:屏幕列
* font:ASCII字符串
* note:注意函数中的unsigned char*类型
*/
void display_ascii(int y, int x, unsigned char *font)
{
unsigned char *p_ascii;
int offset;
unsigned char *p = font;
while (*p != 0) {
offset = (*p – 0x20) * ascii_size;
p_ascii = ascii_code + offset;
__display_ascii(y, x, p_ascii, “*”);
x += 13; /* 12或以上 */
p++;
}
}
/*
* 打印汉字,使用HZK24文件
* fp:汉字库文件指针
* y:屏幕行
* x:屏幕列
* font:汉字字符串
* note:注意函数中的unsigned char*类型
*/
void display_hz(FILE *fp, int y, int x, unsigned char *font)
{
unsigned char mat[24][3]={{0}};
int qh,wh;
unsigned long offset;
unsigned char *p = font;
while (*p != 0) {
qh = *p – 0xaf;
wh = *(p+1) – 0xa0;
debug(“code : %x %xn”, *p, *(p+1));
offset = ( 94*(qh-1) + (wh-1) ) * 72;
//offset = 0;
debug(“qh: %x wh: %x offset: %xn”, qh, wh, offset);
fseek(fp,offset,SEEK_SET);
fread(mat,72,1,fp);
__display_font(y, x, mat, “*”);
x += 24;
p+=2; /* 中文字符,移动2个字节 */
}
}
/*
* 打印字符,中英文混合版本
* fp:汉字库文件指针
* y:屏幕行
* x:屏幕列
* font:字符串
* note:
* 注意函数中的unsigned char*类型
*/
void display_font(FILE *fp, int y, int x, unsigned char *font)
{
unsigned char mat[size][bytes]={{0}};
int qh,wh;
unsigned long offset;
unsigned char *p = font;
unsigned char *p_ascii;
while (*p != 0) {
qh = *p – 0xaf;
wh = *(p+1) – 0xa0;
if (qh > 0 && wh > 0){
debug(“code : %x %xn”, *p, *(p+1));
offset = ( 94*(qh-1) + (wh-1) ) * buf_size;
debug(“qh: %x wh: %x offset: %xn”, qh, wh, offset);
fseek(fp,offset,SEEK_SET);
fread(mat,buf_size,1,fp);
__display_font(y, x, mat, “*”);
x += 25; /* 24或以上 */
p+=2; /* 中文字符,移动2个字节 */
} else {
offset = (*p – 0x20) * ascii_size;
p_ascii = ascii_code + offset;
__display_ascii(y, x, p_ascii, “*”);
x += 13; /* 12或以上 */
p+=1; /* 英文字符,移动1个字节 */
}
}
}
int main()
{
unsigned char incode[] = “我顶ABC”;
FILE *HZK;
initscr(); /* init screen */
if((HZK=fopen(“HZK24S”,“rb”))==NULL) {
perror(“Can’t Open hzk24″);
exit(0);
}
display_font(HZK, 1, 0, incode);
fclose(HZK);
//getch(); /*暂停*/
endwin(); /* close it */
return 0;
}
size命令结果:
text data bss dec hex filename
3042 4892 12 7946 1f0a a.out
修改后的版本:
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <ncurses.h> /* ncurses库头文件 */#include “ascii24.h”
#define ascii_code ascii24
/* for debug */
//#define DEBUG
#ifdef DEBUG
#define debug(fmt, …) printw(fmt, ##__VA_ARGS__)
#else
#define debug(fmt, …)
#endif
#define size 24 /* 点阵规格:24点阵 */
#define bytes (size/8) /* 汉字占用字节:3字节,即分3次取数据 */
#define buf_size (bytes * size) /* 汉字缓冲区大小:3*24 = 72字节 */
#define ascii_bytes (bytes-1) /* 24点阵ASCII码占用字节:2字节,即分2次取数据,与16点阵汉字一样*/
#define ascii_size (size * ascii_bytes) /* ASCII缓冲区大小:24*2 = 48字节 */
/*
使用UCDOS汉字库显示汉字,需转置
y:行
x:列
mat:二维数组
code:显示的字符(如”*”等)
*/
static void __display_font(FILE *fp, int y, int x, unsigned char *s, char *code)
{
unsigned int i, j;
unsigned char mat[24][3]={{0}};
int qh,wh;
unsigned long offset;
qh = *s – 0xaf;
wh = *(s+1) – 0xa0;
debug(“code : %x %xn”, *p, *(p+1));
offset = ( 94*(qh-1) + (wh-1) ) * 72;
debug(“qh: %x wh: %x offset: %xn”, qh, wh, offset);
fseek(fp,offset,SEEK_SET);
fread(mat,72,1,fp);
for(i=0;i<size;i++)
for(j=0;j<size;j++)
if(mat[j][i>>3] & (0x80>>(i&7)))
mvprintw(y+i, x+j, code);
else
mvprintw(y+i, x+j, ” “);
refresh();
}
static void __display_ascii(int y, int x, unsigned char *ascii, char *code)
{
int i, j, k;
unsigned char *p_ascii;
int offset;
offset = (*ascii – 0x20) * ascii_size;
p_ascii = ascii_code + offset;
for(i=0;i<size;i++)
for(j=0;j<ascii_bytes;j++)
for(k=0;k<8;k++)
/* 从高位开始,逐位相与,为1者,输出“*” */
//if(*( p_ascii + i*ascii_bytes+j) & (0x80>>k))
if(p_ascii[i*ascii_bytes+j] & (0x80>>k))
mvprintw(y+i, x+j*8+k, code);
else
mvprintw(y+i, x+j*8+k, ” “);
refresh();
}
/*
* 打印ASCII,使用96个可打印字符版本的ASCII码数组
* y:屏幕行
* x:屏幕列
* font:ASCII字符串
* note:注意函数中的unsigned char*类型
*/
void display_ascii(int y, int x, unsigned char *font)
{
//unsigned char *p = font;
while (*font != 0) {
__display_ascii(y, x, font, “*”);
x += 12; /* 12或以上 */
font++;
}
}
/*
* 打印汉字,使用HZK24文件
* fp:汉字库文件指针
* y:屏幕行
* x:屏幕列
* font:汉字字符串
* note:注意函数中的unsigned char*类型
*/
void display_hz(FILE *fp, int y, int x, unsigned char *font)
{
#if 01
while (*font != 0) {
__display_font(fp, y, x, font, “*”);
x += 24;
font+=2; /* 中文字符,移动2个字节 */
}
#endif
#if 0
/* 比前一种方法多一条指令:i++ */
int i;
for (i = 0; *font; i++, x += 24, font += 2)
__display_font(fp, y, x, font, “*”);
#endif
}
/*
* 打印字符,中英文混合版本
* fp:汉字库文件指针
* y:屏幕行
* x:屏幕列
* font:字符串
* note:
* 注意函数中的unsigned char*类型
*/
void display_font(FILE *fp, int y, int x, unsigned char *font)
{
while (*font != 0) {
if ( (*font – 0xaf) > 0 && (*(font) – 0xa0) > 0) {
__display_font(fp, y, x, font, “*”);
x += 24;
font+=2; /* 中文字符,移动2个字节 */
} else {
__display_ascii(y, x, font, “*”);
x += 12; /* 12或以上 */
font++;
}
}
}
int main()
{
unsigned char incode[] = “我顶ABC”;
FILE *HZK;
initscr(); /* init screen */
if((HZK=fopen(“HZK24S”,“rb”))==NULL) {
perror(“Can’t Open hzk24″);
exit(0);
}
display_font(HZK, 1, 0, incode);
fclose(HZK);
endwin(); /* close it */
return 0;
}
size命令结果:
$ size a.out
text data bss dec hex filename
2802 4892 12 7706 1e1a a.out
近来经济拮据,如本文对阁下有帮助,可慷慨解囊赞助笔者以输出更多好文章。
支付宝[email protected] 或 微信fly_camel_fly 均可。感谢!
本文固定链接: /programming-under-linux/dot-font-24.html