点阵字体显示系列之一:ASCII码字库的显示
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相信会更方便些)查看这个偏移量,会发现有如下数据:
00000410 00 00 10 38 6c c6 c6 fe c6 c6 c6 c6 00 00 00 00 |...8l...........|
所谓的字库,里面就是一些二进制数据。我们看看上面得到“A”的16个字节数据显示效果是怎样的。将上面的十六进制数据按二进制输出,一个字节一行,共占16行,如下:
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);
;
}
由于是示意性代码,不必纠结于代码优化、代码风格等等问题。效果(同样进行了调整)如下:
*
***
** **
** **
** **
*******
** **
** **
** **
** **
***
**
**
****
** **
** **
** **
** **
** **
*****
还有另一种方法,不读取字库,而是将所有的字符存放于某个数组中,比如像font_8x16.c文件中的fontdata_8x16数组。这里假设数组为ascii_code,那么,上面的代码只需修改一小部分,如下:
{
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)个字符在显示中没有用到,因此是可以去掉的,这样一来,寻址方式又稍有不同,如下:
{
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码字库的显示的更多相关文章
- LCD显示——点阵字体
Bitmap font 点阵字体是把每一个字符都分成16×16或24×24个点,然后用每个点的虚实来表示字符的轮廓. 点阵字体优点是显示速度快,不像矢量字体需要计算:其最大的缺点是不能放大,一旦放大后 ...
- 【STM32H7教程】第52章 STM32H7的LTDC应用之点阵字体和字符编码(重要)
完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第52章 STM32H7的LTDC应用之点阵字体和 ...
- Windows7 系统 CMD命令行,点阵字体不能改变大小以及中文乱码的问题
之前装了oracle 11g后,发现开机速度竟然奇葩的达到了3分钟.经过旁边大神指点,说是因为oracle某个(具体不清楚)服务,在断网的时候会不断的ping网络,导致速度变慢.然后就关服务呗,然后一 ...
- 【MM系列】SAP SAP库龄报表逻辑理解
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP SAP库龄报表逻辑理解 ...
- 一点理解之 CmBacktrace: ARM Cortex-M 系列 MCU 错误追踪库
@2019-02-14 [小记] CmBacktrace: ARM Cortex-M 系列 MCU 错误追踪库,用来将单片机故障状态寄存器值翻译出来输出至终端上以便排错 CmBacktrace: AR ...
- 【C++自我精讲】基础系列五 隐式转换和显示转换
[C++自我精讲]基础系列五 隐式转换和显示转换 0 前言 1)C++的类型转换分为两种,一种为隐式转换,另一种为显式转换. 2)C++中应该尽量不要使用转换,尽量使用显式转换来代替隐式转换. 1 隐 ...
- 不显示Zetero导出的文献库中的部分内容
不显示Zetero导出的文献库中的部分内容 Zetero作为文献管理软件,收集到的参考文献的相关信息(域fields)比较齐全.文章或书籍的引用中仅仅只用到了其中的一部分,如作者.发表年.题名.期刊( ...
- 【ABAP系列】SAP 业务界面同时显示KEY和文本
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP 业务界面同时显示KEY和 ...
- 【ABAP系列】SAP ABAP实现LOG显示的方法
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP实现LOG显示的 ...
随机推荐
- 消息队列Handler的用法
下面是每隔一段时间就执行某个操作,直到关闭定时操作: final Handler handler = new Handler(); Runnable runnable = new Runnable() ...
- Golang程序性能分析
前言 程序性能分析我相信是每个程序员都会遇到的问题,比如说一个程序的CPU为什么占用这么高?有没有优化的空间?又比如程序出现了内存泄漏如何排查等等.如果是C++程序会借助于Google pprof c ...
- python 基础 2.6 for 循环 和if循环 中break
python中最基本的语法格式大概就是缩进了.python中常用的循环:for循环,if循环.一个小游戏说明for,if ,break的用法. 猜数字游戏: 1.系统生成一个20以内的随机数 2.玩家 ...
- EasyNVR+EasyDSS实现简单套路的RTMP、微信直播、录像、回放方案
安防领域HLS直播问题探讨 近期外出交流比较多,在之前的一篇博客<一种流量成本节省60%以上的手机直播微信直播H5直播幼儿园直播方案>我们说到了一种模式,就是当我们在做最近火热的幼儿园直播 ...
- mysql双机热备+heartbeat集群+自动故障转移
环境说明:本环境由两台mysql 数据库和heartbeat 组成,一台的ip 为 192.168.10.197,一台为192.168.10.198,对外提供服务的vip 为192.168.10.20 ...
- animate和scrollTop的使用
// 平滑滚动到ola结果位置 var scrollHeight = $("#wrap_div")[0].scrollHeight; var curDivHeight = $(&q ...
- sql server charindex函数和patindex函数详解(转)
charindex和patindex函数常常用来在一段字符中搜索字符或字符串.假如被搜索的字符中包含有要搜索的字符,那么这两个函数返回一个非零的整数,这个整数是要搜索的字符在被搜索的字符中的开始位数. ...
- ArcGIS Overview Map(鹰眼/概览图)
一.说明 引用文件那块,可以参考我上一篇博文,arcgis api for javascript离线部署. 这篇博文中,地图占满整个body 二.运行效果 三.HTML代码 <!DOCTYPE ...
- Webpack探索【8】--- 模块热替换详解
本文主要讲模块热替换相关内容.
- 开源Flex Air版免费激情美女视频聊天室,免费网络远程视频会议系统((Flex,Fms3联合打造))
开源Flex Air版免费激情美女视频聊天室,免费网络远程视频会议系统((Flex,Fms3联合打造)) Flex,Fms3系列文章导航 Flex,Fms3相关文章索引 本篇是视频聊天,会议开发实 ...