当前位置: 首页 > GNU/Linux程序 > 正文

点阵字体显示系列补记2:关于24点阵汉字显示程序及其修改版本

自从写完16点阵后,由于没啥事做,就继续看看24点阵是如何显示的。这种规格的点阵是使用UCDOS(虽然下载了,但用不了)中的汉字字库。又千辛万苦找到ASCII码的24点阵,再修改前面的程序,生成24点阵ASCII码的数组。测试完后,用一天时间,在触摸屏搞出了汉字显示,不过对比了Tslib库的代码,发觉自己写的简直是一塌糊涂,于是继续修改代码。不过,由于不知道如何优化代码及组织代码结构,修改后的成果仅仅是生成的可执行文件大小比原来的版本少240个字节(使用size命令查看得到的结果)。这也算是一个进步吧,网络上关于专门针对某种平台、某种情景的代码优化资料比较少,靠以前和平时一点一点积累,实属不易。

在这里贴上两个版本的源代码,估计没啥人研究这玩意,因此程序不作解释。在不影响代码功能及坚持本人代码风格前提下,尽量减少不必要的行数,对代码中的笔误及其它不影响功能的小毛病,恕不再作修改。

原来的版本:

#include <stdio.h>

#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, 10, incode);

fclose(HZK);

//getch(); /*暂停*/

endwin();  /* close it */

return 0;

}

size命令结果:

$ size a.out

text    data     bss     dec     hex filename

3042    4892      12    7946    1f0a a.out

 

修改后的版本:

#include <stdio.h>

#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, 10, 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

本文固定链接: http://www.latelee.org/programming-under-linux/dot-font-24.html

目前暂无评论

发表评论

*

快捷键:Ctrl+Enter