第23卷第4期 2010年10月
宁波大学学报(理工版) Vol.23 No.4
JOURNAL OF NINGBO UNIVERSITY ( NSEE )

Oct. 2010
文章编号:1001-5132(2010)04-0056-06
基于FreeType嵌入式矢量字体引擎的研究
黄秀珍, 何加铭*, 邰晓英
(宁波大学 信息科学与工程学院, 浙江 宁波 315211)
摘要: 提出了一种嵌入式矢量字体引擎的开发和实现方法. 首先剖析了FreeType开源引擎的体系结构和渲染流程, 然后针对TrueType矢量字体对其裁剪, 包括去掉不相关字体解释器及宏、对轮廓分解算法优化等, 最终在大小和速度上进行优化, 开发出新的字体引擎. 该引擎能很好地适用于存储空间小、运算能力不高的嵌入式系统, 并在MTK平台下测试通过. 关键词: FreeType; TrueType矢量字体; 嵌入式平台 中图分类号: TP317
文献标识码: A
随着嵌入式系统的发展和应用, 在嵌入式系统中使用高质量的汉字字库已成为关注的热点. 尤其是在与人们生活关系日益密切的移动通信设备中, 高效地显示出美观大方的汉字已成为当前主要的市场需求. 目前, 嵌入式系统的字库还是以点阵字为主. 由于点阵字库不能缩放, 因此对于高分辨率屏幕而言, 显示数据量大, 其显示速度比普通的TrueType矢量字库慢[1]. 而在嵌入式系统中使用矢量字体可以实现较好的显示效果, 并且矢量字体可以对字体风格、字体大小、字体的颜色等进行动态渲染. 与传统使用的点阵字库相比, TrueType字库可以高质量地实现字符的无级放大或缩小, 并实现字符的旋转、倾斜等操作, 方便地实现“所见即所得”.
在嵌入式系统中使用矢量字体需要相应的字体引擎. 在PC机上, 通常可以使用FreeType字体引擎来渲染TrueType矢量字库. FreeType库是一个开源字体引擎[2], 它支持单色位图、反走样位图的
渲染, 并且提供统一的接口来访问多种字体格式文件, 包括TrueType、OpenType、Type1、CID、CFF、Windows FON/FNT、X11 PCF等. 少数嵌入式系统可以直接支持FreeType字体引擎[3]. 而对大多数嵌入式系统来说, 由于存储空间和运算能力的限制, 并不能直接使用FreeType字体引擎, 并且在移植时需要对其裁剪优化[4].
1 FreeType字体引擎和TrueType矢
量字体
1.1 TrueType矢量字体
TrueType字体格式是由美国Apple公司和Microsoft公司联合提出的一种新型数字化矢量字体格式, 它采用几何学中的二次B样条曲线及直线来描述字体的外形轮廓. 二次B样条曲线具有一阶连续性和正切连续性. 抛物线可由二次B样条曲线来精确表示, 而更为复杂的字体外形可用B
收稿日期: 2010-03-24. 宁波大学学报(理工版)网址: http://3xb.nbu.edu.cn 基金项目: 科技部创新基金(60472099); 浙江省科技计划项目(2009C31107).
第一作者: 黄秀珍(1983-), 女, 江西永修人, 在读硕士研究生, 主要研究方向: 网络与终端软件技术. E-mail: hxzjxsd1983@yahoo.com.cn *通讯作者: 何加铭(1949-), 男, 浙江杭州人, 博导/教授, 主要研究方向: 网络与终端软件技术. E-mail: hejiaming@nbu.edu.cn
第4期 黄秀珍, 等: 基于FreeType嵌入式矢量字体引擎的研究 57
样长曲线的数学特性以数条相接的二次B样条曲线及直线来表示.
描述TrueType字体的文件(内含TrueType字体描述信息、指令集、各种标记表格等)可以通用于MAC和PC平台. 在Mac平台上, 它以“Sfnt”资源的形式存放, 而在Windows平台上以TTF文件出现. 为保证TrueType的跨平台兼容性, 字体文件的数据格式采用Motorola式数据结构(高位在前, 低位在后)存放. 所有Intel平台的TrueType解释器在执行之前, 只要进行适当的预处理即可. Windows的TrueType解释器已包含在其GDI(图形设备接口)中, 所以任何Windows支持的输出设备都能用TrueType字体输出. 1.2 FreeType字体引擎
FreeType库使用ANSI C开发的开源字体引擎, 因此, FreeType的用户可以灵活地对它进行裁剪, 并且, 它可以被用在诸如图像库、展出服务器、字体转换工具、图像文字产生工具等多种产品上. 移动通信平台中引入FreeType字体引擎有以下优势: (1)占用的存储容量小, FreeType库文件通过裁剪定制可减少存储大小和运行时间; (2)渲染字体清晰美观, 字体大小和风格可变.
为了使FreeType字体引擎定制到嵌入式系统, 需要对其进行裁剪. 在32位嵌入式系统下, 存储容量的大小是嵌入式系统处理矢量字库的一个瓶颈, 这就需要我们深入研究其体系结构及渲染流程, 以做进一步的裁剪优化.
2 FreeType体系结构和渲染流程
在使用FreeType字体引擎显示字符时, 需要调用其模块化函数, 其中的每个函数都是封装一个功能模块的组件.
其具体步骤如下: 首先建立初始化类库, 装载Face信息, 然后设置字体大小, 并设置轮廓信息, 最后将轮廓渲染为位图信息. 其具体流程图如图1
所示.
图1 FreeType字符显示流程
对应流程图的步骤说明如下:
(1) 首先对FreeType库进行初始化, 并且读取矢量字库文件.
FT_Init_FreeType(&library);
FT_New_Face(library,filename,0,&face); 这里的library是个全局变量, 而filename是矢量字库的路径, 通过以上2个步骤首先建立了1个FreeType库的实例. 通过FT_New_Face加载1个TrueType矢量字库, 得到字体的face对象接口.
(2) 设置当前像素尺寸.
使用函数FT_Set_Pixel_Size(face,0,size)来完成设置当前像素尺寸, 也可以使用函数FT_Set_ Char_Size(), 但要注意后面的函数设置的大小不是以像素为单位的.
(3) 设置字符的轮廓信息.
由于在TrueType文件格式中, 每个字符的轮廓信息是根据字形索引来存放的, 所以首先需要根据字符的编码来得到字形索引, 代码如下:
FT_Get_Char_Index(face,charcode);
从face中来得到字符对应的字形后, 需要读取到字形槽中才能使用.
FT_Load_Glyph(face,glyph_index,FT_LOAD_DEFAULT);
Get_Glyph(face->glyph,&glyph); 最后提取字形槽中的字形图, 即点阵信息.
FT_Glyph_To_Bitmap(&glyph,FT_RENDER_
MODE_NORMAL,0,1);
58 宁波大学学报(理工版) 2010
bitmap_glyph = (FT_BitmapGlyph)glyph; 经过上述过程转化之后, 字符的位图信息就存放在bitmap_glyph的参数里面, 嵌入式系统GDI就可以把这个字符显示出来.
(4) 改变字体风格.
粗体的显示直接调用FT_GlyphSlot_Embolden (face->glyph). 由于FreeType中没有直接对斜体的支持, 所以需要自己对矢量的字形轮廓进行变换, 定义变换矩阵后进行如下变换:
error = FT_Set_Transform( face, /* 目标face对象 */
&matrix, /* 指向2×2矩阵的指针 */ &delta ); /* 指向2维矢量的指针 */ 此函数将对指定的face对象设置变换. 它的第2个参数是1个指向FT_Matrix结构的指针. 该结构描述了1个2×2仿射矩阵. 第3个参数是1个指向FT_Vector结构的指针, 该结构描述了1个简单的二维矢量, 该矢量用来在2×2变换后对字形图像平移.
3 裁剪与优化
由于FreeType库中的API都是封装好的组件, 其中的具体实现细节只在源码中才能查看到. 通过对源码的分析, 笔者去除了一些无关的定义及步骤, 裁剪和改进了一些算法.
首先, 在对FreeType库进行初始化时, 去除FT_Library和FT_Face等复杂的类对象. 由于FreeType中采用了面对对象的思想编程, 因此其包含了TrueType、Type1、CID、CFF、Windows FON/ FNT、X11 PCF等多个字体驱动的抽象接口, 并使用抽象的类来统一所有字体驱动初始化过程. 而这里我们只需用到格式TrueType矢量字体, 不需要对字体驱动进行判断, 可直接使用TrueType字体driver.
在对TrueType字体进行初始化时, 首先要载
入其各个表项. 将Library对象、face对象的创建和初始化以及对字体平台驱动的判断都简化为TrueType中各个重要表项的载入, 以对应初始化字体的相关参数.
设置字体大小部分比较简单. 主要是根据指定的字体大小, 确定缩放的规模及缩放后字体的规格参数: 如额定的宽度和高度、EM正方形的像素宽度和高度等. 而此部分也不用face对象等结构体.
取得字符轮廓是字符渲染的关键步骤. 在FreeType中有多种字体, 也有多种字符轮廓, 这里我们只用TrueType字符轮廓的载入方法. 首先用函数FT_Get_Char_Index取得字符索引, 查找方法为有线性查找和二分查找. 对有序数据使用二分法查找字符索引, 然后根据字符索引和local表中偏移量得到glyf表中的图元信息. 载入图元信息时, 首先载入图元头, 然后载入简单图元, 最后再处理图元信息.
最后轮换的图元数据为点阵信息时, 可选择使用smooth渲染器. 它能生成256色位图信息, 字体边缘并且有渐变的效果. 在进行渲染时, 先将作平移操作, 以调整到相对目标窗口的位置. 然后计算出Control Box的值, 最后将轮廓分解、光栅化填充. 3.1 读取字库
去除不相关的字体driver初始化, 直接使用TrueType字体driver初始化. 首先是打开字库文件, 读取初始化信息. 由于TrueType矢量字体是以多个表的形式来包含组成字体轮廓的数据, 因此字体引擎需要各表的信息来渲染其字体. 接着读取表目录. 每个表都有1个tableentry结构项, 而tableentry结构包含了资源标记、校验和、偏移量和每个表的大小. 由于TrueType字体中的每个表都保存了不同的逻辑信息, 如图元中数据、字符到图元的映射、字距调整信息等等. 因此, 有些表是必须的, 而有些是可选的. 然后依次读取常用表的
第4期 黄秀珍, 等: 基于FreeType嵌入式矢量字体引擎的研究 59
信息, 包括: head, maxp, cmap, hhea, vhea, hmtx, vmtx, loca等. 3.2 设置字体大小
主要是对函数FT_Set_Pixel_Sizes的实现部分做了优化. 原函数实现部分主要在FT_Request_ Size的几个函数, 主要是按照设置的字体高度和宽度取得字体缩放的各个参数, 用到数学中的除法函数FT_DivFix、FT_MulFix及取整函数FT_PIX_ CEIL等.
3.3 取得字符轮廓信息
首先取得字符的字形索引, 函数FT_Get_ Char_Index()中主要使用的是二分法查找cmap表中字形索引, 而不使用线性查找法.
然后根据字形索引和偏移查找字符对应的图元信息. 图元数据(glyf表)是TrueType字体的核心信息, 通常它是最大的表. 因为, 位置索引是张单独的表, 而图元数据表则完全只是图元的序列而已; 每个图元以图元头结构开始, 简单图元中保存了当前图元的轮廓线的数目, 合成图元的轮廓线总数必须基于组成该合成图元的所有图元的数据计算得到. 对于简单图元而言, 图元的描述紧跟在图元头结构之后. 图元的描述由几部分信息组成: 所有轮廓线结束点的索引、图元指令和一系列的控制点. 每个控制点包括1个以x和y坐标的标志. 概念上来讲, 控制所需的信息和GDI函数PolyDraw函数所需的信息相同, 都是1组标志和1组点的坐标. 图元可以包含1条或多条轮廓线. 比如, 汉字“宋”有3条轮廓线和若干控制点, 图2为其控制点的显示
.
图2 宋体的“宋”字的控制点信息
TrueType字体中的图元轮廓是用二阶Bezier
曲线定义的, 具体有3个点: 1个曲线上的点, 1个曲线外的点和另1个曲线上的点. 多个连续的不在曲线上的点是允许的. 3.4 轮换图元数据为点阵信息
在3.3小节中, 主要是从字库中提取图元信息, 而本节则根据图元信息进行作图和填充. 作图是根据关键点画直线和贝塞尔曲线, 然后是光栅填充, 此时, 以将填充后的字模提取并缩小保存(字模一般是2048×2048).
FreeType缺省带了2个渲染器: raster支持从向量轮廓(由FT_Outline对象描述)到单色位图的转换; smooth支持同样的轮廓转换到高质量反走样的象素图, 其使用256级灰度. smooth渲染器也支持直接生成span. 在此, 由于我们需要得到是高质量反走样的位图, 所以使用的是smooth渲染器.
首先, 进行轮廓曲线分解. 1个轮廓是2D平面上一系列封闭的轮廓线, 每个轮廓线由一系列线段和Bezier弧组成. 应用如下规则于将轮廓点分解成线段和弧.
2个相邻的“on”点表示1条线段; 1个conic off点在2个on点之间表示1个conic Bezier弧, off点是控制点, on点是起点和终点; 2个相邻的cubic off点在2个on点之间表示1个cubic Bezier弧, 它必须有2个cubic控制点和2个on点. 最后, 强制在2个相邻的conic off点的正中间创建1个虚拟的on点.
装入或变换过的轮廓必须在渲染成目标位图之前作平移操作, 以调整到相对目标窗口的位置.
4 实验与讨论
首先, 在MTK模拟器上测试. 运行环境如下: PC机CPU 2.17GHz, 内存1GB, 相应软件平台为
VC 6.0. 图3中MTK平台为已有的点阵字体显示. 而在模拟器上, 字体显示效果如图4和图5所示.
图4和图5中显示的字体为TrueType矢量字
百度搜索“爱华网”,专业资料、生活学习,尽在爱华网!