点阵字体及矢量字体的数学原理和实现.docx
- 文档编号:4313525
- 上传时间:2022-11-29
- 格式:DOCX
- 页数:38
- 大小:65.12KB
点阵字体及矢量字体的数学原理和实现.docx
《点阵字体及矢量字体的数学原理和实现.docx》由会员分享,可在线阅读,更多相关《点阵字体及矢量字体的数学原理和实现.docx(38页珍藏版)》请在冰豆网上搜索。
点阵字体及矢量字体的数学原理和实现
毕业设计(论文)
题目名称:
矢量字体的数学原理及其显示实现
院系名称:
理学院
班级:
信科081
学号:
4103
学生姓名:
卜令杰
指导教师:
周忠
2012年5月
矢量字体的数学原理
及其显示实现
TheMathematicalPrincipleofVectorFontsandItsDisplayAccomplishment
院系名称:
理学院
班级:
信科081
学号:
4103
学生姓名:
卜令杰
指导教师:
周忠
2012年05月
摘要
本文先研究了点阵字体的存储原理及其16*16点阵字体实现,进而认识到点阵字体的缺陷,即点阵字体大小固定单一,在放大时虽然速度较快,但效果不好,很难达到美观的要求,同时对矢量字体进行了探秘。
介绍了矢量字体的数学原理,即贝塞尔曲线的绘图原理,并且实现了楷体矢量字库中字体的显示及其放大显示。
关键词:
点阵字体,矢量字体,贝塞尔曲线,字库
ABSTRACT
Thispaperfirstlystudiesthestorageprincipleofbitmapfontsanditsrealizationofthe16*16dotmatrixfont,andthenrecognizesthedefectsofbitmapfonts,namely,thesizeofthebitmapfontsisfixedandsingle.Bitmapfontszoomsinfaster,buttheeffectisdifficulttoachievetheaestheticrequirements.Atthesametime,inthispaperweexplorethevectorfonts.Inaddition,thispaperintroducesthemathematicalprinciplesofthevectorfont,namely,thedrawingprincipleoftheBeziercurveandrealizesthedisplayofthefontsinitalicsvectorfontanditsmagnifieddisplay.
Keywords:
Bitmapfonts,Vectorfonts,Beziercurve,Font
1简介
1.1背景知识
点阵字体是把每一个汉字都分成16×16或24×24个点,然后用每个点的虚实来表示汉字的轮廓,常用来作为显示字库使用,这类点阵汉字最大的缺点是一旦放大后就会发现文字边缘的锯齿,很难达到美观的效果。
矢量字体(Vectorfont)中每一个字形是通过数学曲线来描述的,它包含了字形边界上的关键点,连线的导数信息等,字体的渲染引擎通过读取这些数学矢量,然后进行一定的数学运算来进行渲染。
这类字体的优点是字体实际尺寸可以任意缩放而不变形、变色。
矢量字体又叫Outlinefont,通常使用贝塞尔曲线,绘图指令和数学公式进行绘制。
这样可以在对字体进行任意缩放的时候保持字体边缘依然光滑,字体色素不会丢失。
目前主流的矢量字体格式有3种:
Type1,TrueType和OpenType,这三种格式都是平台无关的。
Type1全称PostScriptType1,是1985年由Adobe公司提出的一套矢量字体标准,由于这个标准是基于PostScriptDescriptionLanguage(PDL),而PDL又是高端打印机首选的打印描述语言,所以Type1迅速流行起来。
但是Type1是非开放字体,Adobe对使用Type1的公司征收高额的使用费。
TrueType是1991年由Apple公司与Microsoft公司联合提出另一套矢量字标准。
Type1使用三次贝塞尔曲线来描述字形,TrueType则使用二次贝塞尔曲线来描述字形。
所以Type1的字体比TrueType字体更加精确美观。
一个误解是,Type1字体比TrueType字体占用空间多。
这是因为同样描述一个圆形,二次贝塞尔曲线只需要8个关键点和7段二次曲线;而三次贝塞尔曲线则需要12个关键点和11段三次曲线。
然而实际情况是一般来说Type1比TrueType要小10%左右。
这是因为对于稍微复杂的字形,为了保持平滑,TrueType必须使用更多的关键点。
由于现代大部分打印机都是使用PDL作为打印描述语言,所以True1字体打印的时候不会产生形变,速度快;而TrueType则需要翻译成PDL,由于曲线方程的变化,还会产生一定的形变,不如Type1美观。
这么说来,Type1应该比TrueType更具有优势,为什么如今的计算机上TrueType反而比Type1使用更广泛呢?
这是因为第一:
Type1由于字体方程的复杂,所以在屏幕上渲染的时候,花费的时间多,解决方案是大部分Type1字体嵌入了点阵字体,这样渲染快,但是边缘不光滑,比较难看。
很多ps文档和ps转换的pdf文档都是这样,在计算机上浏览的时候字体很难看,但是打印出来很美观。
TrueType则渲染比较快,可以平滑的显示在屏幕上,看上去很美观。
第二个原因是Type1的高额使用费,使得Type1没有被所有的操作系统所支持。
Windows家族只有OS/2和windows2000及之后的版本从操作系统级别开始支持Type1。
由于这个问题,Adobe只好在其所有的产品中嵌入AdobeTypeManager(ATM)作为渲染引擎。
OpenType则是Type1与TrueType之争的最终产物。
1995年,Adobe公司和Microsoft公司开始联手开发一种兼容Type1和TrueType,并且真正支持Unicode的字体,后来在发布的时候,正式命名为OpenType。
OpenType可以嵌入Type1和TrueType,这样就兼有了二者的特点,无论是在屏幕上察看还是打印,质量都非常优秀。
可以说OpenType是一个三赢的结局,无论是Adobe,Microsoft还是最终用户,都从OpenType中得到了好处。
Windows家族从Windows2000开始,正式支持OpenType。
1.2论文目的概述
由于点阵字体具有大小固定单一,在放大缩小时虽然速度较快,但效果不好,特别是在放大时,字体边缘出现锯齿,很难达到美观的效果,所以就出现了矢量字体。
矢量字体具有放大而不变形等优点,本文论述了矢量字体的数学原理尤其是贝塞尔曲线的绘图原理以及矢量字体的显示。
2点阵字体的实现原理
2.1汉字点阵字库的原理
2.1.1区位码
在国标GD2312—80中规定,所有的国标汉字及符号分配在一个94行、94列的方阵中,方阵的每一行称为一个“区”,编号为01区到94区,每一列称为一个“位”,编号为01位到94位,方阵中的每一个汉字和符号所在的区号和位号组合在一起形成的四个阿拉伯数字就是它们的“区位码”。
区位码的前两位是它的区号,后两位是它的位号。
用区位码就可以唯一地确定一个汉字或符号,反过来说,任何一个汉字或符号也都对应着一个唯一的区位码。
汉字“母”字的区位码是3624,表明它在方阵的36区24位,问号“?
”的区位码为0331,则它在03区3l位。
2.1.2机内码
汉字的机内码是指在计算机中表示一个汉字的编码。
机内码与区位码稍有区别。
如上所述,汉字区位码的区码和位码的取值均在1~94之间,如直接用区位码作为机内码,就会与基本ASCII码混淆。
为了避免机内码与基本ASCII码的冲突,需要避开基本ASCII码中的控制码(00H~1FH),还需与基本ASCII码中的字符相区别。
为了实现这两点,可以先在区码和位码分别加上20H,在此基础上再加80H(此处“H”表示前两位数字为十六进制数)。
经过这些处理,用机内码表示一个汉字需要占两个字节,分别称为高位字节和低位字节,这两位字节的机内码按如下规则表示:
高位字节=区码+20H+80H(或区码+A0H)
低位字节=位码+20H+80H(或位码+AOH)
由于汉字的区码与位码的取值范围的十六进制数均为01H~5EH(即十进制的01~94),所以汉字的高位字节与低位字节的取值范围则为A1H~FEH(即十进制的161~254)。
例如,汉字“啊”的区位码为1601,区码和位码分别用十六进制表示即为1001H,它的机内码的高位字节为B0H,低位字节为A1H,机内码就是B0A1H。
2.1.3点阵字库结构
在汉字的点阵字库中,每个字节的每个位都代表一个汉字的一个点,每个汉字都是由一个矩形的点阵组成,0代表没有,1代表有点,将0和1分别用不同颜色画出,就形成了一个汉字,常用的点阵矩阵有12*12,14*14,16*16三种字库。
汉字的显示和输出,普遍采用点阵方法。
由于汉字数量多且字形变化大,对不同字形汉字的输出,就有不同的点阵字形。
所谓汉字的点阵码,就是汉字点阵字形的代码。
存储在介质中的全部汉字的点阵码又称为字库。
16x16点阵的汉字其点阵有16行,每一行上有16个点。
如果每一个点用一个二进制位来表示,则每一行有16个二进制位,需用两个字节来存放每一行上的16个点,并且规定其点阵中二进制位0为白点,1为黑点,这样一个16X16点阵的汉字需要用2×16即32个字节来存放。
依次类推,24×24点阵和32×32点阵的汉字则依次要用72个字节和128个字节存放一个汉字,构成它在字库中的字模信息。
要显示或打印输出一个汉字时,计算机汉字系统根据该汉字的机内码找出其字模信息在字库中的位置,然后依次读取这32个字节的内容,并且把它依次显示出来就可以得到汉字的点阵形式。
汉字点阵字库是根据区位码的顺序进行存储的,因此,我们可以根据区位码来获取一个字库的点阵,它的计算公式如下:
点阵起始位置=((区码-1)*94+(位码–1))*汉字点阵字节数
减1是因为文件中的偏移量是以0为开始而区号位号是以1为开始的,需要换算一下。
获取点阵起始位置后,我们就可以从这个位置开始,读取出一个汉字的点阵。
例如下面的语句:
qh=*(hz)-0xa0;//汉字区位码
wh=*(hz+1)-0xa0;
offset=(94*(qh-1)+(wh-1))*32;//计算该汉字在字库中偏移量
通过这样的语句我们可以得到一个汉字在字库中的偏移量,然后我们将这32个字节(一个汉字)的点阵字模存在一个二维数组中,字模虽然也是一组数字,但它的意义却与数字的意义有了根本的变化,它是用数字的各位信息来记载英文或汉字的形状,从而我们就可以得到汉字或英文的显示图案。
我们根据这个二维数组中每一位的信息来确定该汉字在该点位上的情况,然后依次显示出每一位的情况,从而得到该汉字的点阵形式[4]。
2.2.汉字的点阵显示实现
我们现在根据上面的汉字点阵显示原理,编写程序实现16*16点阵汉字的显示。
其程序的具体实现见附录一。
程序运行的结果如图1所示:
图1
3矢量字体的实现原理
3.1矢量字体的分类
矢量字体主要包括Type1、TrueType、OpenType等几类。
Type1全称PostScriptType1,使用三次贝塞尔曲线来描述字形,TrueType则使用二次贝塞尔曲线来描述字形而OpenType是二者的结合。
3.2矢量字库结构
矢量字体不是用点阵信息描述汉字的笔划,而是将汉字的笔划边缘用直线段描述成封闭的曲线,并将线段各端点的坐标经压缩存储,它是以图形信息建库的。
由于每个汉字的笔划不一样,所以每个汉字在库中所占长度是不相同的。
这样,矢量字库不能象点阵那样定位,只能采用索引的方法。
因而每种矢量字库都是由两部分组成,一部分是汉字的索引信息,它包括每个汉字的矢量数据在库中的位置地址以及汉字字形数据的长度,存放在字库的前面部分,按汉字的区位码顺序存放;另一部分是汉字的字形数据,包括控制信息和各点坐标信息,是字库的主体,放在字库的后面。
如UCDOS的矢量字库HZKSLSTJ(宋体简体)、HZKSLFSJ(仿宋简体)、HZKSLKTJ(楷体简体)、HZKSLHTJ(黑体简体),其索引信息长度6个字节,前面四个字节是汉字矢量数据在库中的起始位置,后两个字节为汉字字形数据的长度。
要进行矢量汉字显示,首先根据其机内码按下面公式:
汉字的索引信息首址=((汉字机内码高位字节-0Xa1)*94+汉字机内码低位字节-0Xa1)*6
计算出其索引信息首址,然后从指定的矢量字库按索引地址连续读出6个字节的索引信息,再根据索引信息中字形数据在库中的位置及字形数据的长度,从库中读出字形数据在库中的位置及字形数据的长度,从库中读出相应的字形数据,最后解码还原得到其轮廓多变形的各点坐标,画出多边形并填充,即可得到矢量汉字[6]。
3.3UCDOS矢量字库结构
UCDOS矢量字库有索引区和矢量数据区两部分组成,如下图所示[2]。
3.3.1索引信息
根据汉字的内码计算得到其索引信息在矢量字库中的位置,计算公式如下:
索引位置=((区码-16)•94+位码-1)•6
索引信息指明了某字的矢量数据在矢量字库中的位置和尺寸(以字节为单位),其中位置是相对于字库开始处以字节为单位的位移量。
3.3.2矢量数据
矢量数据区中的数据有绘制某汉字的所有矢量信息,这些信息又以笔伐为一个数据组,每组占有若干个字节。
这些字节中的首字节指明了该笔的起点,后续一个或多个字节指明了相对前一点增量及增量的方向。
3.3.3矢量数据的组织方法
矢量数据由x坐标的增量
、
坐标的增量
以及增量的方向组成。
其中,增量方向通常用一个二进制位表示,且规定0表示正向,1表示反方向。
因为笔划的不同,其
、
的值也不同,因此占用字节数及数据位数均不一样。
在UCDOS矢量字库中,为了节省空间没有对不同情况的
、
规定统一的字节数,而是将矢量数据首字节的最高两位设定为标志位,标志位的四种状态表示四种不同的情况,每种情况占用二个或若干个字节不等。
具体情况分析如下[3]:
①D7=1D6=1
如果首字节最高两位均为1,则表示一个笔划的开始,该字节后六位与下一个字节的最高位表示起始点的x坐标值,下一个字节的剩余七位表示起始点的y坐标。
②D7=1D6=0
首字节最高位为1,次高位为0,此根据D5、D4的取值确定x、y的增量。
当D5D4等于00或01时,x、y的增量值必定一个较大一个较小。
在这两种情况下,字节1的后三位为小增量的增量值,D3的增量方向,而下一字节的后七位表示大增量的增量值,最高位(D7)为相应增量方向。
当D5D4等于10或11时,x、y的增量值都较大。
故在这两种情况下,紧接下二个字节为x、y的增量值和增量方向。
③D7=0D6=1
首字节最高位为0,次高为1,表示该笔具有连续若干增量,且增量值较大。
此时该字节的D5、D4表示增量的方向,当前字节的后四位表示增量方向上的坐标点数,我们记为Count。
随后的Count个字节为增量值,其中高四位为
、低四位为
。
④D7=0D6=0
首字节最高两位均为0,则后六位为矢量点的个数,我们也记为Count。
此时表示该笔有连续若干增量,且相对于前一种情况(D7=0D6=1),其每个增量值较小,但Count的值较大。
随后的Count个字节表示增量值及增量的方向,其中高四位为x坐标的增量及增量的方向,低四位为y坐标的增量及增量方向。
3.4矢量字体的数学原理
矢量字体主要有Type1、TrueType、OpenType,Type1用三次贝塞尔曲线来描述字形轮廓;TrueType使用二次贝塞尔曲线来描述字形而OpenType是两者的结合。
下面介绍一下贝塞尔曲线[1]:
贝塞尔曲线是多项式调和函数推导出来的,通常n+1个顶点定义一个n次多项式。
其参数向量表达式为:
在上式中,
为各顶点的位置向量,
为伯恩斯坦基函数,也就是贝塞尔多边形的各顶点位置向量之间的调和函数。
该函数的表达式为:
如果我们规定:
均为1,那么,当t=0时:
当t=1时:
从以上结果可以得出,曲线通过多边折线的起点和终点。
下面,我们通过对基函数求导,来分析一下曲线在两个端点处的切矢。
所以:
在起点处,t=0
在终点处,t=1
这说明:
贝塞尔曲线在两端点处切矢方向是与贝塞尔多边折线的第一条边和最后一条边相同的。
我们已经知道,确定n+1个顶点,可以定义一条n次的贝塞尔曲线。
下面,我们来讨论一下低次贝塞尔曲线,例如二次和三次贝塞尔曲线。
当n=2时,顶点
可定义一条二次贝塞尔曲线。
此时
写成矩阵为:
此时的调和函数
分别为:
当n=2时,二次贝塞尔曲线在起点
处有切向量
;在终点
处有切向量
。
同时,当t=1/2时;
当n=3时,顶点
四点可定义一条三次贝塞尔曲线,此时:
同样,该式写成矩阵表达式为:
此时相应的调和函数
分别为:
4SPDOS6.0矢量字库结构及显示实现
4.1SPDOS6.0矢量字库结构
SPDOS6.0PostScript汉字字体中一个关键技术就是使用三次贝塞尔曲线,是构成每个轮廓的线段和曲线之间能平滑连接(连接点一阶连续),从而保证了字体任意放缩不变形。
SPDOS6.0中的PostScript汉字字体文件遵循以下命名规则:
扩展名.PS、文件名为?
?
DOT。
黑体字库的文件名为HTDOT.PS。
在八种字体(黑体、楷体、宋体、仿宋、标宋、行楷、隶书、魏碑)中,除行楷、隶书、魏碑三种都是由简单字组成之外,其余几种都是既有简单字,又有复合字(这种字由几个简单的偏旁部首按照一定的放缩比例复合而成)。
为表示一般性,以后面五种字体文件为例。
整个字库文件按偏移顺序分为四个部分:
汉字字形索引区、汉字数据区、汉字偏旁索引区、汉字偏旁数据区[5]。
汉字字形索引区的长度为20307个字节,其中包括了6768个汉字字形数据的入口偏移地址索引和1个用于确定第6768个汉字字形数据结束偏移地址的索引,每个索引的长度为3个字节。
如果给定区码为qm,位码为wm的汉字,((qm-16)*94+wm-1)*3就给出了该字索引的入口地址,从而得到字形数据。
汉字字形数据区的起始偏移地址为20308,长度依字库不同而不一样,但各个字库字形数据的解释、控制方法是一样的,具体组织结构如下:
【控制符1】+
个坐标或偏旁索引数据+【控制符2】+
个坐标或偏旁索引数据+…
其中,控制符是以半个字节为单位,数据是一字节为单位,但这个字节既可以是一般的字节,也可以是由两个半字节顺序组合而成的。
下面,用表1详细说明各个控制符的作用,其中,
表示数据位X或Y坐标,
表示是一个偏旁索引,X,Y表示当前坐标。
表1
控制符
后跟数据
功能描述
0
当前点移位到
1
从(X,Y)画线到
2
从(X,Y)画线到
3
从(X,Y)画线到
4
以此三(四)点作二(三)次B曲线
5
6
以
为两顶点作矩形
8
以
确定一个新区间,在此区间内按比例绘制第
个偏旁
9
a
汉字偏旁索引区的规则与汉字字形索引区基本一致,所不同的是偏旁索引给出的是偏旁部首的入口地址。
另一方面,除了8,9,a三种情况外,偏旁数据区与汉字字形数据区的规则是完全一样的。
4.2楷体矢量字库(KTDOT.PS)中字体的显示实现
楷体矢量字库(KTDOT.PS)中字体的显示程序见附录2。
运行结果如图2。
图2
4.3楷体矢量字库(KTDOT.PS)中字体的放大显示实现
楷体矢量字库(KTDOT.PS)中字体的放大显示程序见附录3。
运行结果如图3。
图3
总结
本文从点阵字体出发,分析了其存储原理,通过C语言编程,实现了点阵字体的显示,从而发现了点阵字体的缺陷。
于是对矢量字体进行了探究,分析了矢量的实现原理,即控制码、坐标和贝塞尔曲线,通过编程实现了矢量字体的显示,进而发现其优点。
但由于时间和个人能力有限,没有能对各种矢量字库一一了解。
例如,由于没有找到UCDOS3.0的字库,所有没能实现这种矢量字体的显示。
因此这一问题有待于在今后的学习中进一步的解决和完善。
但本文也基本完成了论文目的,理解了矢量字体的原理,了解到了矢量软件的一些应用,并且在论文的最后实现了矢量字体的显示,提高了对其原理的认识和理解。
通过本篇论文的论述,同学们应该了解到了点阵字体的原理及其实现和矢量字体的数学原理及其部分矢量字体的显示。
由于矢量字体具有放缩而不变形等优点,使它的应用非常的广泛。
参考文献
[1]尹世明,黄红军,哀国强.SPDOS6.0中PostScript三次曲线汉字字库解[J].中国图像图形学报.1996.2
[2]马艳华,王前虹.USDOS矢量字库结够分析[J].衡阳师范学报.1996
[3]徐雨明.POSTSCRIPT曲线字库的结构和直接显示方法[J].衡阳师专字报.1997
[4]沈一喆.点阵字库任意角度旋转的算法实现与应用[J].软件导刊.2008.10.
[5]徐雨明.Bezier曲线在轮廓字中的应用[J].五邑大学学报.1997
[6]吴永祥.矢量汉字库结构分析及矢量汉字的显示[J].十堰大学学报.1994.3
致谢
从论文的选题到搜集资料,从写稿到反复修改,期间经历了喜悦、聒噪、痛苦和彷徨,在写论文的过程中心情是如此复杂。
如今,伴随着这篇论文的最终成稿,复杂的心情烟消云散,自己甚至还有一点成就感。
毕业论文结稿,同时我的四年大学生活也随之即将结束。
回首四年的大学生活,真的有太多太多的感想。
首先,我要特别的感谢我的指导老师周忠老师,他给了我莫大的帮助。
给了我矢量字体及其字库的大体分类和程序实现。
这篇毕业论文从开题、资料查找、修改到最后定稿,都有老师的帮助,我很自豪有这样一位老师,他值得我感激和尊敬。
其次,感谢和我共度四年美好大学生活的2007级信息与计算科学专业的全体同学,感谢理学院和理学院的所有授课老师,你们使我终身受益,我会永远记得我这些可爱的老师和同学的。
最后,我要感谢我的父母,他们无私的关爱和支持是人生道路的动力之源和坚强后盾。
附录一
#include
#include
usingnamespacestd;
intRead_Hzk16(int(*matrix)[16],char*hz)
//intRead_Hzk16(intmatrix[][16],char*hz)
{
ifstreamah("HZK16",ios:
:
binary);
charbuffer[32];//buffer用来存储一个汉字
registerinti,j,k;
unsignedcharqh,wh;
unsignedlongoffset;
if(ah.fail())return0;
qh=*(hz)-0xa0;//汉字区位码
wh=*(hz+1)-0xa0;
offset=(94*(qh-1)+(wh-1))*32L;//计算该汉字在字库中偏移量
ah.seekg(offset,ios:
:
beg);//fseek(fp,offset,SEEK_SET);
ah.read(buffer,32);//fread(buffer,32,1,fp);//取出汉字32字节的点阵字模存入buffer中(一个汉字)
for
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 点阵 字体 矢量 数学 原理 实现