点阵字体显示系列补记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 %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,  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 %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,  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


 

©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页