Foxdisk11-小字库显示汉字2

刚从大学毕业那会,对操作系统极其入迷,总想搞清楚底层是怎么运行的。其中最感兴趣的是图形的显示,BIOS对硬件的控制等。找了很多资料看,正好公司的一些项目上也需要用到,就这么磕磕碰碰的实现了各种显示的代码。

Foxdisk的代码中,Vesa.c和Vesa.h就包含了显示的所有信息。主要是遵循了vesa的标准进行显示,采用C嵌汇编的方式来编写。目前,几乎所有的机器都支持VESA标准,而在X86平台下编程就是基于此标准的。VESA标准在原有BIOS提供的API的基础上,提供了一组扩展BIOS功能调用。对于标准VGA下的模式,仍然可以使用基本BIOS调用,但对于扩展模式,其许多操作如模式设置及视频缓冲读写等,则只能通过VESA标准提供的扩展BIOS来实现。

在VESA标准下,视频缓冲是以分页映射的方式进行操作。其基窗口一般为在0xA0000处,每页为64K。整个视频缓冲都通过映射到此窗口而得以直接存取。一般的图形编程步骤如下:

  • 设置显示模式(如0x103为 800×600 256色的配置)
  • 设置颜色寄存器
  • 按照图形显示的原理编写画点、画线、画圆等基本函数。

过多的细节不用纠结,Vesa.c中提供了画点函数putpixel256()。把屏幕当做一个大画布,设置模式的时候知道这块画布多大,用画点函数绘制即可。Foxdisk使用的是模式0x105,也即1024×768,256色。想像一下,有张宽1024像素点,长768像素点的画布,有支可在画布任何坐标处画点的笔,应该是什么画都可以画出来了,包括汉字。

Foxdisk中显示汉字,大致可以分为两步:

  1. 提取需要的汉字字模,保存到程序内部;
  2. 调用Font.c中显示汉字的函数,将需要的汉字显示在屏幕上。

Vesa.c和Font.c中屏蔽了很多显示的细节,特别是对各种字体及字体大小的处理。在设计之初,考虑去兼容各种不同的字体,比如黑体、楷体、宋体等等。代码中针对不同的字体,提供了各种编译用的开关。实际程序中,主要用了16×16宋体和24×24楷体,从提取汉字库的批处理命令可以看出来。

在博客“Foxdisk09-工具篇”中,已经初略的介绍了提取汉字库的工具了。我是为了能自动针对所有用到汉字的代码,自动提取汉字字模,开发的这些小工具。下面具体介绍下如何提取字库。

所谓无字库技术,就是在程序中建立一个类似字库的字库数组来代替字库。程序中建立的字库某种意义上独立于程序中显示程序。也就是存在这样的可能:单独对字库数组进行压缩,在使用的时候重新解压。这个特性在嵌入式的应用中非常有用,可以节约不少的程序空间。

一般说来,提取汉字字库的步骤应该是这样的:

1) 对包含需要提取汉字的源文件进行文法分析,析取出需要提取字模的汉字

2) 对提取出的汉字再次分析,并去除重复的汉字打开相应的汉字库,提取需要的字模,并按规则形成新的字库数组

3) 对照上一篇博客的说明,设计16×16及24×24的汉字字模结构体。

struct       hzk16_typ{         /*  汉字字模结构体  */

  unsigned int code;

  unsigned int array[16];

};

struct       hzk24_typ{         /*  汉字字模结构体  */

  unsigned int code;

  unsigned char array[3*24];

};

最终会将字模以上述数据结构的方式存储,Foxdisk中存储生成的文件为HZTABLE.H和HZK24.H。

具体的提取代码可以参照ehz24.c和etrhz.c,这两个文件的代码量都在400行左右。核心工作在于分析指定的文件,从中提取出需要转换字模的汉字。

为了便于分析,也为了程序编写简单,对指定的文件是有要求的。必须保证在提取的文件中字符串中没有//和/* 字符,否则可能会提取错误。提取程序并没有去进行字符串内部的语义分析,否则要处理的情况太多了。 代码就不贴出来了,放不下。对照编程的想法,以及代码,还是比较容易看明白运作的机制的。

发表评论

电子邮件地址不会被公开。