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、可以搜索一下字库生成工具,用这些工具可以生成需要的字库。

点阵字体显示系列之一:ASCII码字库的显示的更多相关文章

  1. LCD显示——点阵字体

    Bitmap font 点阵字体是把每一个字符都分成16×16或24×24个点,然后用每个点的虚实来表示字符的轮廓. 点阵字体优点是显示速度快,不像矢量字体需要计算:其最大的缺点是不能放大,一旦放大后 ...

  2. 【STM32H7教程】第52章 STM32H7的LTDC应用之点阵字体和字符编码(重要)

    完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第52章       STM32H7的LTDC应用之点阵字体和 ...

  3. Windows7 系统 CMD命令行,点阵字体不能改变大小以及中文乱码的问题

    之前装了oracle 11g后,发现开机速度竟然奇葩的达到了3分钟.经过旁边大神指点,说是因为oracle某个(具体不清楚)服务,在断网的时候会不断的ping网络,导致速度变慢.然后就关服务呗,然后一 ...

  4. 【MM系列】SAP SAP库龄报表逻辑理解

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP SAP库龄报表逻辑理解   ...

  5. 一点理解之 CmBacktrace: ARM Cortex-M 系列 MCU 错误追踪库

    @2019-02-14 [小记] CmBacktrace: ARM Cortex-M 系列 MCU 错误追踪库,用来将单片机故障状态寄存器值翻译出来输出至终端上以便排错 CmBacktrace: AR ...

  6. 【C++自我精讲】基础系列五 隐式转换和显示转换

    [C++自我精讲]基础系列五 隐式转换和显示转换 0 前言 1)C++的类型转换分为两种,一种为隐式转换,另一种为显式转换. 2)C++中应该尽量不要使用转换,尽量使用显式转换来代替隐式转换. 1 隐 ...

  7. 不显示Zetero导出的文献库中的部分内容

    不显示Zetero导出的文献库中的部分内容 Zetero作为文献管理软件,收集到的参考文献的相关信息(域fields)比较齐全.文章或书籍的引用中仅仅只用到了其中的一部分,如作者.发表年.题名.期刊( ...

  8. 【ABAP系列】SAP 业务界面同时显示KEY和文本

      公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP 业务界面同时显示KEY和 ...

  9. 【ABAP系列】SAP ABAP实现LOG显示的方法

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP实现LOG显示的 ...

随机推荐

  1. 修复open-ssl漏洞,升级open-ssl版本

    升级openssl环境至openssl-1.0.1g 1.查看源版本 [root@zj ~]# openssl version -a OpenSSL 0.9.8e-fips-rhel5 01 Jul ...

  2. 在mac下搭建java开发环境

    刚刚从windows系统转到使用mac系统.感觉不是特别熟悉,须要一定的适应时间. 以下简介一下mac下搭建主要的java开发环境. 1.安装jdk 安装jdk1.7后,发现不须要进行环境变量配置,直 ...

  3. php eval()计算

    php中的eval()函数可以处理php代码,因此可以用此来解决:以字符串格式存储的计算公式 比如: $str='2*(3+12)'; $s=eval("return $str;" ...

  4. Centos7重新安装yum

    Centos7重新安装yum rpm -qa|grep yum 然后用下面的命令删除出现的xxx包: rpm -e --nodeps xxx 下载 python-urlgrabber-3.10-8.e ...

  5. HTML5(石头剪刀布游戏开发)

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  6. MongoDB API java的使用

    1.创建一个MongoDB数据库连接对象,它默认连接到当前机器的localhost地址,端口是27017. Mongo mongo=new Mongo(); 2.获得与某个数据库(例如“test”)的 ...

  7. 【题解】P2048 [NOI2010]超级钢琴

    [题解][P2048 NOI2010]超级钢琴 一道非常套路的题目.是堆的套路题. 考虑前缀和,我们要是确定了左端点,就只需要在右端区间查询最大的那个加进来就好了.\(sum_j-sum_{i-1}​ ...

  8. 开发笔记--java.lang.OutOfMemoryError: PermGen space异常处理

    第一次到公司开发项目,比起之前的小项目来说这次的项目特别大,以至于运行之后出现了java.lang.OutOfMemoryError: PermGen space的异常,从字面意思上来看是内存溢出的原 ...

  9. PAT 甲级 1041. Be Unique (20) 【STL】

    题目链接 https://www.patest.cn/contests/pat-a-practise/1041 思路 可以用 map 标记 每个数字的出现次数 然后最后再 遍历一遍 找到那个 第一个 ...

  10. [egret+pomelo]实时游戏杂记(3)

    [egret+pomelo]学习笔记(1) [egret+pomelo]学习笔记(2) [egret+pomelo]学习笔记(3) 服务端的请求流程走完了一遍,下面就该看一下,在目前的服务端中,各服务 ...