Chinaunix首页 | 论坛 | 博客
  • 博客访问: 300740
  • 博文数量: 134
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 118
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-01 14:02
文章分类

全部博文(134)

文章存档

2015年(2)

2014年(4)

2013年(128)

分类: 嵌入式

2013-12-01 11:06:31

原文地址:QT字体库 作者:进击的菜鸟


1、首先将下载好的字体库copy到开发板qt目录下的/lib/fonts目录下
2、移植好字体库到/lib/fonts后需要在此目录下创建一个fontdir文件
格式为:

                        wenquanyi wenquanyi_120_50.qpf  QPF n 50 120 u
                        wenquanyi wenquanyi_120_75.qpf  QPF n 75 120 u
                        wenquanyi wenquanyi_130_50.qpf  QPF n 75 130 u
                        wenquanyi wenquanyi_150_75.qpf  QPF n 75 150 u
                        wenquanyi wenquanyi_160_75.qpf  QPF n 75 160 u

                        可以看到共有七列
                        第一列:字体的名字,就是你在设置字体的时候的字体的名字
                        第二列: (file)即具体的文件名字
                        第三列: (renderer)字体的格式,有BDF,TTT,QPF等选择.
                        第四列: n 表示iitalic,是否为斜体
                        第五列:weight, 50 = Nomal,75=Bold
                        第六列: size 120表示12pt
                        第七列flags 有三个选项:s   (smooth)
                                                      u   (unicode顺序保存)
                                                      a   (ascii 顺序保存,默认是Latin 
                        1)。

 文件中每行都标识一个特定的字库,每个段的含义是:第一列为name,第二列为file,第三列为renderer,相当于字型格式,所以有 
                        BDF,TTT,QPF等选择。第四列n表示iitalic,表示是否为斜体字。第五列表示weight,其中50表示Normal,75表示Bold。第六列表示size,例如:120表示12pt。第七列为flags,有下面三个选择:s=smooth(anti-aliased)u 
                        =unicode range when saving (default is Latin 1 a = ASCII 
                        range when saving(default is Latin 1))
                                                                                 
                        —— 摘自参考文献[1]
                            
                        其中属性file,renderer(BDF,TTF,QPF)和size特别要设置对,其它属性问题不大。还要注意如果在该目录下有QPF的文件,系统只会使用QPF格式的文件,而不会读取其它格式的文件,不管FONTDIR里面的内容是什么。如果有多个QPF文件,应用程序按照大小,家族,黑体和斜体的顺序查找,即首先查找大小和自己一样的字库,大小无法区分唯一的字库的再看对应的家族,还是无法区分的再看是否黑体,是否斜体。可以参考PC上的字库索引文件FONTDIR:
                        例如:
                        -cclib -song -medium -r -normal -jiantizi -16 -160 -75 
                        -75 -c -160 -gb2312 1980 -0
                        其中,每个段的含义如下:
                        cclib:制造商
                        song:字体族,此处表示“宋体”字
                        medium:字权重(中等),还有bold(粗体)选项
                        r:倾斜,R(Roman),I(Italic),O(Oblique)
                        normal:字符集宽度,此外还有condensed,narrow,double
                        jiantizi:附加说明(此处意义为“简体字”)
                        16:用像素衡量的宽度。
                        160:点数 10
                        75(1):水平分辨率(dpi)
                        75(2):垂直分辨率(dpi)
                        c:间距。c:square,m:fixed width,p:variable width
                        160:平均宽度(10*pixels)
                        gb2312.1980:注册字符集,标准名
                        0:第0套,基本集
                                                                              —— 
                        摘自参考文献[2]

                        1.2 几种格式字库的简介
                            
                        QT支持四种格式的字库(TTF,BDF,PFA/PFB,QPF)(见参考文献[3]),但在产品中,如果直接使用,TTF或PFA/PFB。即让应用程序在显示的时候再计算点阵,最终的效果并不理想,会发现有些字大,有些字小,而且需要占用非常多的FLASH和内存,速度也有点慢,所以我在此不想过多的介绍PFA/PFB。如果直接使用BDF,速度非常慢,而且需要占用比较多的FLASH和内存;使用QPF,速度和占用其它资源是最小的,因此我们最终的产品中采用QPF格式。下面我简单介绍,TTF,BDF和QPF字体的结构,这样就比较容易理解后面的转换过程。

                        1.2.1  TTF字体
                           TTF(TrueType 
                        Font)是Apple公司和Microsoft公司共同推出的字体文件格式,随着Windows的流行,已经变成最常用的一种字体文件表示方式。TTF 
                        字体已经成功用在Windows中文版生成汉字字库,此字体采用二次B样条曲线来描述字符轮廓,对字符轮廓的上的点,按顺时针方向从小到大编号,填充部分在其右边。TTF文件结构分成三个部分:文件名(12Bytes),描述表目录(每个16Bytes),描述表数据。
                            
                        对于每一个字,都有一个假想的矩形框,正常情况字是不会超出这个矩形框的,中文属于象形字,不象英文,大小不一致,比如:英文中的f就可能会超出矩形框。微软把矩形的高度称为EM,实际字符的高度称为BODY.矩形框最原始的坐标系是矩形的中心为原点,但为了实际字体在打印和显示的使用过程中的方便,通常将坐标原点放在左下角,或中下。
                            
                        通常,在实际打印过程中,TTF字体是用像素来度量的,如何将矩形框中的字体转成像素呢?有一个计算公式,实例如下:如果18个点的72点每英寸屏下有一个550的长度,矩形框内有2048个单位。那其像素为550*18*72/72/2048=4.83像素。显然,每英寸里的点取的越多,字就越逼真,同时这样的存储空间和计算的时间也就越多。在嵌入程序开发过程中,这往往是不可以接受的,因为嵌入式系统的硬件资源本来就很有限,如果真的这样的话,在显示过程会很慢。并且如果为了提高速度而减少每英寸中的点数,则字体失真的情况很严重。更加具体的关于,TTF字体的内容可见参考资料[3]。
                            
                        另外,在Windows下编程,Microsoft实现了让用户对字体操作处理具有透明性,有关字体结构定义见参考文献[4]。

                        1.2.2 BDF字体
                            BDF(Bitmap Distribution 
                        Format)是在X窗口系统中的一种表示位图字体的文件格式。是X协会定义的一种标准,是ASCII文件它由两部分组成,一是表示字体整体属性的文件头信息;二是每一个字符独有的属性和位图数据。我以16*16的位图字体为例描述BDF字体文件格式。
                        STARTFONT2.1 /*后面跟一个版本号,指出该字体文件版本*/
                        COMMENT /*表示注释*/
                        FONT -adobe -courier -bold -r -normal -16 -160 -75 -75 
                        -m -160 -gb2312.1980 -0 
                        /*表示字体名*/
                        SIZE 16 75 75 /*字符大小与在X,Y方向上的分辨率*/
                        FONTBOUNDINGBOX 16 16 0 0 /*X方向上宽度与Y方向高度及x和Y方向上的偏移*/
                        STARTPROPERTIES 16 /*设置字体的属性项目数*/
                        FOUNDRY "Adobe" /*字体的制造厂家*/
                        FAMILY_NAME "Courier" /*字体的变种字型*/
                        WEIGHT_NAME "Bold" /*字体的印刷权*/
                        SLANT "R" /*字体字型的设计情况*/
                        SEWINDTH_NAME "Normal" /*字体的缩放因素*/
                        ADD_STYLE_NAME "" /*唯一的标识该字体,一般为空*/
                        PIXEL_SIZE 16 /*依赖于设备的字体尺寸*/
                        POINT_SIZE 160 /*设计字体的实际尺寸*/
                        RESOLUTION_X 75 /*设计字体的水平分辨率*/
                        RESOLUTION_Y 75 /*设计字体的垂直分辨率*/
                        SPACING "m" /*指出字符宽度是定长还是可变*/
                        AVERAGE_WIDTH 160 /*字体中所有字符的平均宽度*/
                        CHARSET_REGISTRY "gb2312.1980" /*字符集名*/
                        CHARSET_ENCODING "0" /*字符集编号*/
                        FONT_DESCENT 0 /*基线下的高度*/
                        FONT_ASCENT 16 /*基线上的高度*/
                        ENDPROPERTIES /*属性项设置结束*/
                        CHAR 6775 /*字体文件中的字符数*/
                        STARTCHAR 啊 /*字符起始标志及名称*/
                        ENCODE 3021 /*X服务器在存取该字符时使用的编码。如汉字国标码*/
                        SWIDTH 1000 0 /*X和Y方向上的逻辑宽度和高度*/
                        DWIDTH 16 0 /*字符在x和Y方向上的设备单位宽度*/
                        BBX 16 16 0 0 /*字符边界框的宽度,高度以及偏移*/
                        BITMAP /*字符的位图的信息起始标志*/
                        0000 /*字符位图*/
                        04a0
                        ……
                        0590
                        ENDCHAR /*字符结束标志*/
                        STARTCHAR 阿 /*第二个字符开始*/
                        ……
                        ENDFONT /*BDF字体文件结束标志*/

                        1.2.3 QPF字体简介
                            
                        QPF格式的字库是仅用于QT/Embedded的不可缩放的字体,在程序运行过程中,对TTF格式的字体,在第一次装入使用时,都要以给定的字体大小进行处理;而对于BDF字体,当其使用时,所有字体都必须被处理;而对于QPF字体,均以相同格式的存储。所以在字体显示时,Qt只要读取字体,做相应分析,然后显示就完成了,这样进一步减少了对RAM资源的浪费。QPF字体是基于UNICODE编码的,这为QT/Embedded良好的可移植性奠定了基础。有关QPF更详细的资料可以查阅参考文献[5]。
                        2 如何从TTF字体文件转成QPF字体文件
                        2.1 把TTF转换成BDF
                            
                        尽管不推荐使用TTF格式的字库,但由于TTF格式的字库可以转换成任意大小的BDF字库,而可以找到的BDF字库都是固定大小的,因此在实际制作QPF字体文件时,还是需要TTF格式的字库。把TTF转换成BDF的方法如下:
                        ./ttf2bdf source.ttf -p yourSize -o destination.bdf
                            
                        即利用软件ttf2bdf可以把源文件source.ttf转换成大小为yourSize的BDF格式的文件destination.bdf。那在程序内部是如何实现将TTF转成BDF的呢?由2.2.1和2.2.2的介绍,并且查阅参考文献[3],可以知道TTF的内部存储结构。其中最核心的部分是 
                        TTF文件格式中的12个字节的文件表:表目录按tag以升序排列。

                              TypeNameDescription
                              ULONG tag4字节的标识
                              ULONGcheckSum表中的CheckSum
                              ULONGoffsetTrueType font文件的起始偏移量Offset
                              ULONGlength表长


                            还有一个有关Offset表的信息,包括版本号,表的数量,查找范围。入口选择,转换范围。
                            
                        通过操作文件表,将描述表中的数据取出来,按照BDF字体所定义的格式写入,就可以生成对应的字体。比如,可以给出一小段c语言程序,此程序用于计算当前CheckSum的位置。
                        ULONG
                        CalcTableChecksum(ULONG *Table,ULONG Length)
                        {
                        ULONG Sum = 0L;
                        ULONG *Endptr=Table+((Length+3)& ~3)/sizeof(ULONG);
                        while(Table                         Sum += *Table++;
                        return Sum;
                        }
                            
                        利用此程序可以将每个字体的信息分开,并将每个字体信息从文件中取出来,对每个字体进行操作。在从TTF转到BDF过程中,仅通过使用WINDOW的函数是很不方便的,最方便的办法是使用c语言对字体进行操作。我在此列出转换过程中最重要的几个值:PIXEL_SIZE,POINT_SIZE,RESOLUTION_X,RESOLUTION_Y,FONT_DESCENT,FONT_ASCENT,SWIDTH,DWIDTH,BBX。这些值决定着最后生成的BDF字体与TTF字体的失真度,因为TTF是可缩放的,而BDF是固定大小的,所以在转换过程中一定会出现失真的情况。

                        2.2 对得到的BDF文件进行调整
                            
                        由于从软件xmbdfed里得到的三个字库不符合系统的要求,因此需要手动对其进行一些调整,其它方法得到的BDF文件不需要进行调整。
                        直接从xmbdfed里得到的字库是按照GB2312-80.0进行编码的,因此首先要将其转换成符合UNICODE编码,这需要用到我手动写的一个程序 
                        gb2unieode,把源文件拷贝到gb2unicode程序的目录下,将其名字改为hanzist24a.txt(程序的要求,也可以不改名字而修改程序里源文件的名字再重新编译),然后运行./change之后,就完成了,因为QT中因现成的转换函数可以调用,在此我不想多说关于用程序转换的代码。因为有一种更简单的方法,即在Word中打开GB字库。然后另存为UNICODE字库文件就行了。
                            
                        等待该命令执行完后(注意需要的时间比较长),对所生成的文件dest.txt进行排序,方法如下:把dest.txt的名字改为dest.bdf(只要后缀名为bdf就行);然后运行软件xmbdfed,用其打开该文件(xmbdfed只能直接打开后缀明为bdf的文件),另存为 
                        yourname.bdf即可。排完序后需要手
                        动修改处理yourname.bdf。
                            
                        由上面介绍的BDF字体格式,现在对转换得到的BDF字体文件进行如下手工处理:先删除行说明属性默认的字符的行DEFAULT_CHAR 
                        8481,因为从GB2312转换成UNICODE后,编码为8481的字符已经不存在了,如果不删除该行,运行时会出现段错误。然后删除那些存在于两个 
                        16号字库但在标准GB2312中没有的一些字模。标准GB2312中有7445个字模,而两个16字库有7612个字模,多出来的那部分在用 
                        gb2unicode转换的时候因为找不到相应的GB2312码而没有写进dest.txt的字模开始行"STARTCHAR 
                        ****"。可以用xmbdfed打开,如果出错则说明还有一些不完整的字模,还需要手动删除这些不完整的字模,如果可以正确打开则说明目标文件已经是正确的。(24号字库不存在这个问题,因此不需要进行本项操作。)最后从其它大小相同的.bdf文件中拷贝编码为20-7F(ASCII码)和编码为 
                        FE54(分号;)的字模到目标文件。

                        2.3 把TTF.BDF转换成QPF
                            
                        从参考文献[5]中可以知道QT提供的把TTF,BDF转换成QPF的方法有两种,一种是工具makeqpf,这个命令无论是在Pc机上还是在开发板上都没有效果(但是QT的官方网站却说是可以的,不知道为什么,并且,也不是每个版本的QT都有makeqpf这个工具,还要说明的是,文献[6]中说这个工具是可以的,不过我没有试验成功)。
                            另一种是运行应用程序时加上选项-savefonts,如在开发板上运行应用程序的命令:./sulfur 
                        -qws -savefonts

                           
                        如果此时系统中/usr/qt/lib/fonts目录下没有QPF格式的字库而只有TTF或BDF格式的字库,对应的文件fontdir中只保留要转换的文件的行,QT就会在运行时首先生成QPF格式的字库。尽管通过TTF字体也可以得到QPF字体,不过最好不要这样做,因为失真太大。

{

本人移植心得:

    我在网上下载了一个名叫“wqy-zenhei.ttf”的字库(存放在我的yeah邮箱中),将其放在文件系统中Qt目录的lib/fonts目录下,并在该目录下新建了一个fontdir的文件,其内容为

wenquanyi-24 wqy-zenhei.ttf FT n 50 240 u 
wenquanyi-36 wqy-zenhei.ttf FT n 50 360 u

即生成24号和36号字体,可根据实际情况增减。

  然后再Qt程序中

   ui->label->setText(tr("字体测试"));//前提已经设置tr要使用的编码,否则可能会出现乱码。

   ui->label->setFont(QFont("wenquanyi-24"));//因为在fonts目录下没有wenquyi-24的QPF文件,因此会根据fontdir的内容将wqy-zenhei.ttf转换一种需要的字号。

同样如果想设置36号字体则可这样做

ui->label->setFont(QFont("wenquanyi-36"));

在开发板上运行命令 ./test -qws -savefonts &   

要加-savefonts

程序运行时首先根据Qt程序中设置的文件如“ui->label->setFont(QFont("wenquanyi-36"))”到QFonts目录中查找对应文件名为“wenquanyi-36”的QPF文件,若找到则调用它,若找不到,则根据fontdir中的内容“wenquanyi-36 wqy-zenhei.ttf FT n 50 360 u”生成一个(该文件实际上在开发板上看不到),生成时依赖“wqy-zenhei.ttf”,因此在font目录下也需要“wqy-zenhei.ttf”字库文件。

缺点:由于“wqy-zenhei.ttf”有十几兆,因此比较占空间。

可用Qt的tools目录下提供的工具先制作QPT文件,不过我编译工具时报错没成功,不过我想应该可行。具体操作如下(来自网友)

QT中QPF字库的制作与旋转字体的实现  
2009-9-8 13:12:00 来源: 
 一、前言 
Qt可以支持以下四种形态的字体格式:TrueType (TTF),Postscript Type(PFA/PFB),Bitmap Distribution Format fonts(BDF),Qt Prerendered Font(QPF)。 
如果直接使用TTF或PFA/PFB。即让应用程序在显示的时候再计算点阵,最终的效果并不理想,会发现有些字大,有些字小,而且需要占用非常多的FLASH和内存,速度也有点慢,如果直接使用BDF,速度非常慢,而且需要占用比较多的FLASH和内存;使用QPF,速度和占用其它资源是最小的,因此我们的嵌入式产品中的QT软件都是采用QPF格式的。 
另一方面,嵌入式应用中,QT界面在LCD中可能是采用旋转的形式显示,如7寸屏,而QT中旋转显示时,需要旋转字体库的支持,否则将无法正常显示文字。所以针对旋转的应用需要利用makeqpf制作旋转的字体库。 
二、字库制作 
1)环境准备 
需要安装好QT2及以上版本 
编译好两个工具:qvfb,makeqpf 
这两个工具都在$QTDIR/tools下, 编译即可 
2)准备ttf字库文件 
可以在自己的windows系统下发现ttf后缀的文件 
此处作者采用网上下载的wqy-zenhei.ttf字库文件 
将所要的文件拷贝到你的linux系统的$(QTDIR)/lib/fonts目录下 
3)修改fontdir文件 
cd $(QTDIR)/lib/fonts 
打开fontdir,加入如下信息: 
wenquanyi wqy-zenhei.ttf FT n 75 160 u 
wenquanyi wqy-zenhei.ttf FT n 50 160 u 
wenquanyi wqy-zenhei.ttf FT n 50 180 u 
wenquanyi wqy-zenhei.ttf FT n 75 180 u 
这些信息的含义如下: 
name1: 任意名 
wqy-zenhei.ttf 文件名 
FT: 表示是ttf文件 
n : y表示是斜体,n表示正常 
50: 表示是正常,75表示是粗体 
160:表示是16点大小的字体,可根据需要修改 
u:表示是unicode的 
4)字库生成 
首先,执行qvfb,然后执行makeqpf.你会在 qvfb的显示窗内看到fontdir中每一行的信息。 
在makeqpf界面中,点击要转换的字库,生成的新的.qpf文件就会存放到$(QTDIR)/lib/fonts/下了 
5)旋转字体库的制作 
使用带参数的方式执行makeqpf,如 
./makeqpf -display Transformed:Rot90 
以上指令用于制作翻转90度的字库文件,制作其它的字库文件只需将270改为90,180,0等 
注:在$(QTDIR)/lib/fonts/ 目录下的qpf字体文件中,文件名中带有t5,t10,t15等后缀的为旋转字体库,t5为旋转90度,t10为旋转180度,t15为旋转270度。如wenquanyi_160_50_t5.qpf  
}

                        3 总结
                            
                        经过本人对字库进行上述处理后,就可以在嵌入式开发板上显示各种字体,只要找到给定TTF或BDF的字库,如果找不到BDF字库,可以找到字库,然后通过 
                        TTF2BDF这个程序来得到BDF字库。这样在开发板上可以显示行书,楷书等字体,并且字体显示也很正常,不会出现大小不一致的问题。但是,本人认为,由于这是嵌入式开发,存储资源非常有限,如果能进一步将字库缩小,只留下程序中所要用的汉字组成的字库就好了,这是需要下一步研究的方向。
                        参考文献:
                        [1] 
                        [2] 
                        = 
                        viewtopic&t=82950&highlight=fonts.dir
                        [3] Microsoft Corporation. TTF Technical Specification 
                        Revision 1.66 November 1995.
                        [4] Windows 2000编程核心技术精解[M].中国水利水电出版社,2001.
                        [5] 
                        [6] 黄敬群.Qt/Embedded中文处理实战[M]


阅读(2276) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~