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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#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 %x/n", *p, *(p+1));
                offset = ( 94*(qh-1) + (wh-1) ) * 72;
                //offset = 0;
                debug("qh: %x wh: %x offset: %x/n", 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 %x/n", *p, *(p+1));
                        offset = ( 94*(qh-1) + (wh-1) ) * buf_size;
                        debug("qh: %x wh: %x offset: %x/n", 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命令结果:

1
2
3
$ size a.out 
text data bss dec hex filename
3042 4892 12 7946 1f0a a.out

修改后的版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#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 %x/n", *p, *(p+1));
        offset = ( 94*(qh-1) + (wh-1) ) * 72;
        debug("qh: %x wh: %x offset: %x/n", 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命令结果:

1
2
3
$ size a.out 
text data bss dec hex filename
2802 4892 12 7706 1e1a a.out