http://blog.csdn.net/subfate/article/details/6444578

起因:

早在阅读tslib源代码时就注意到里面有font_8x8.c和font_8x16.c两个文件(后来才得知,它们来自Linux内核,具体目录是./drivers/video/console),它们包含了在屏幕上显示所需的所有字符(当然,是可打印字符),由此也看了一下tslib显示字符的代码。对将来在触摸屏上显示汉字有所帮助,——这是后话,暂且按下不提。

上面所说的字符当然是ASCII码了,这种编码学过计算机的人可能会很熟悉,就不多讲了。本文所述者,就是通过ASCII码字库文件(网上有下载)和上面提到的其中之一的文件在终端上显示ASCII字符。这也为研究汉字显示打下基础(此为假话,写文章及做作所需也,实际上本文作者是先研究汉字显示再研究ASCII码显示的,勿模仿,切切)。

本文中使用的字库是8x16,每个字符占用内存空间为16字节(后面不再提及),文中显示字符所做工作有下面几步(显示汉字也差不多,当然,这又是后话 ):

1、打开字库文件(似乎是废话);

2、计算出要打印的字符在字库文件中的偏移量(亦即网上所说的“寻址”);

3、将这个偏移地址的数据(16字节)读取缓冲区中;

4、显示这个缓冲区,为1者打印,为0者留空。(由于是在终端上显示,因此,可以使用如“#”、“*”等字符代替。)

先说说如何找到某个字符在字库文件中的偏移量。字库里的字符排序是符合ASCII码顺序的,而每个字符占16字节,因此,将要打印的字符与16相乘,便得到这个字符在字库中的位置了,这个位置之后的16个字节的数据,就是这个字符了。比如大写字母“A”,十六进制是0x41(“A”还是十进制的65、八进制的101,其实都是一回事),它与0x10(十进制的16)相乘,得到0x410(计算机中使用十六进制十分方便,对于某些试题要求计算出某地址的十进制,我表示不理解,既不直观,又不方便,还容易出错)。使用十六进制编辑器(用UE相信会更方便些)查看这个偏移量,会发现有如下数据:

$ hexdump -C ../HZK/ASC16 | grep 410

00000410  00 00 10 38 6c c6 c6 fe  c6 c6 c6 c6 00 00 00 00  |...8l...........|

所谓的字库,里面就是一些二进制数据。我们看看上面得到“A”的16个字节数据显示效果是怎样的。将上面的十六进制数据按二进制输出,一个字节一行,共占16行,如下:

00000000

00000000

00010000

00111000

01101100

11000110

11000110

11111110

11000110

11000110

11000110

11000110

00000000

00000000

00000000

00000000

不直观,将出现0的地方留空,则变成如下形状(受网页影响,为美观起见进行调整,虽非实际中二进制所示,但形状是一致的):

                

                

      1        

    111      

  11  11    

11      11  

11      11  

1111111  

11      11  

11      11  

11      11  

11      11  

                

                

                

                

上面的便是传说中的“A”了。

下面就用代码读取字库信息,并显示出来。完整代码如下:

/***************************************************

 源代码文件编码:ANSI

 测试环境编码:zh_CN.UTF-8、zh_CN.gd2312

 * ************************************************/



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



#ifdef DEBUG

#define debug(fmt, ...) printf(fmt, #__VA_ARGS__)

#else

#define debug(fmt, ...)

#endif





void display_font_ascii(char *asc)

{

        int i, j;

        debug("=================/n");

        ;i<;i++)

        {

                ;j<;j++)

                {

                        /* 逐位相与,为1者打印“*”,否则打印空格 */

                        if(asc[i] & (0x80>>j))

                                printf("*");

                        else

                                printf(" ");

                }

                printf("/n");

        }

        debug("=================/n");

}



int main()

{

        int i;

        unsigned char *p;

        unsigned char asciicode[] = "Ab";

        unsigned long offset;

        FILE *asc;

        ];



        if((asc=fopen("ASC16","rb"))==NULL)

        {

                perror("Can't Open ASC16");

                exit();

        }



         /* ASCII字库文件 */

        ; i < ; i++)

        {

                debug("%c %x/n", asciicode[i], asciicode[i]); /* 打印数值 */

                offset = asciicode[i]*;

                debug("offset: %x/n", offset); /* 打印偏移量 */

                fseek(asc,offset,SEEK_SET);

                fread(ascii,,,asc);              /* 读取16字节 */

                display_font_ascii(ascii);        /* 显示 */

        }

        fclose(asc);



        ;

}

由于是示意性代码,不必纠结于代码优化、代码风格等等问题。效果(同样进行了调整)如下:

$ ./a.out             

                

                

      *        

    ***      

  **  **    

**      **  

**      **  

*******  

**      **  

**      **  

**      **  

**      **  

                

                

                

                

                

                

***          

  **          

  **          

  ****      

  **  **    

  **    **  

  **    **  

  **    **  

  **    **  

  *****    

                

                

                

                


还有另一种方法,不读取字库,而是将所有的字符存放于某个数组中,比如像font_8x16.c文件中的fontdata_8x16数组。这里假设数组为ascii_code,那么,上面的代码只需修改一小部分,如下:

 for (i = 0; i < sizeof(asciicode)-1; i++)

 {

  debug("%c %x/n", asciicode[i], asciicode[i]);

  offset = asciicode[i]* 16; // 寻址

  p = ascii_code+offset;    // 查找字符在ascii_code数组中的偏移量

  debug("offset: %x/n", offset);

  display_font_ascii(p);

 }

效果是一样的,所不同的是,前一种方法需要读取字库文件,后一种方法直接在内存中读取,完整的ASCII码占用空间为4KB。不过,ASCII中可打印的字符共96个(经过认真数那些可打印的字符,发现实际上是95个(即32号到126号),这里将127号算上了,具体的请搜索一下ASCII),占用空间为96*16,即1536字节。由于前面0x20(即32)个字符在显示中没有用到,因此是可以去掉的,这样一来,寻址方式又稍有不同,如下:

 for (i = 0; i < sizeof(asciicode)-1; i++)

 {

  debug("%c %x/n", asciicode[i], asciicode[i]);

  offset = (asciicode[i] - 0x20 )* 16; // 寻址

  p = ascii_code+offset;    // 查找字符在ascii_code数组中的偏移量

  debug("offset: %x/n", offset);

  display_font_ascii(p);

 }

由于文中涉及知识、代码、字库文件都可以在网络上找到,因此文中就不提供下载了。

资料:

1、ASCII码字库,有多种形式,如8*16、8*12,名称为ASC12、ASC16,搜索一下就能找到。

2、“字库数组”,可以在Linux内核源代码的./drivers/video/console目录下找到很多相关代码文件,如font_8x8.c、font_8x16.c、font_sun8x16.c等等。像font_8x16.c文件,代码中说是由cpi2fnt这个东西产生的,但搜索一下,没什么介绍,英文的又不想去看,对这个东西也就不了解了。

3、可以搜索一下字库生成工具,用这些工具可以生成需要的字库。

最新文章

  1. 基于华清远见STM32f051的 IIC从模式实现方法
  2. 「LINUX资料」Samba服务器(二)
  3. git乱码问题解决
  4. OpenCV Template Matching Subpixel Accuracy
  5. 《linux备份与恢复之二》3.19 dump(文件系统备份)
  6. 199. Binary Tree Right Side View
  7. 【转】JS跨域(ajax跨域、iframe跨域)解决方法及原理详解(jsonp)
  8. vs2010 js代码折叠
  9. linux中vi编辑器
  10. for练习--侦察兵
  11. 《C++ 标准库》读书笔记 - 第二章 Introduction to C++ and the Standard Library
  12. hadoop MapReduce - 从作业、任务(task)、管理员角度调优
  13. JavaScript高级程序设计-13:事件
  14. linux 巨页使用测试
  15. 在chrome 怎么通过ajax请求加载本地文件
  16. LeetCode第十一题-可以装最多水的容器
  17. Easyui学习整理笔记
  18. Python 基础:分分钟入门
  19. 简单的CSS圆形缩放动画
  20. JAVA MyBatis使用技巧收集

热门文章

  1. 【转】【Axure学习】之短信动态验证码+图片动态验证码
  2. React中key的必要性与使用
  3. 【BZOJ2229】[Zjoi2011]最小割 最小割树
  4. EasyNVR RTSP转RTMP-HLS流媒体服务器前端构建之:内部搜索功能的实现
  5. (1)Web 应用是一个状态机,视图与状态是一一对应的。 (2)所有的状态,保存在一个对象里面。
  6. hadoop 小文件 挂载 小文件对NameNode的内存消耗 HDFS小文件解决方案 客户端 自身机制 HDFS把块默认复制3次至3个不同节点。
  7. 【题解】CF264B Good Sequences
  8. SAP FI 科目代码
  9. Android Development Note-01
  10. (转)nginx-rtmp-module和ffmpeg搭建实时HLS切片