解析 Qt 字库移植并能显示中文 (下篇)

原文http://mobile.51cto.com/symbian-272563.htm

本文介绍的是Qt 字库移植并能显示中文,需要的字体库文件,一般是多个。具体移植那一个,看你使用的字库是什么了,先来看内容。

AD:

解析 Qt 字库移植并能显示中文 (下篇)是本节介绍的内容,接着上篇 解析 Qt 字库移植并能显示中文 (上篇)继续介绍,烂来看本节内容。

1、几种格式字库的简介

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

(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]。

(2)BDF字体

BDF(Bitmap Distribution Format)是在X窗口系统中的一种表示位图字体的文件格式。是X协会定义的一种标准,是ASCII文件它由两部分组成,一是表示字体整体属性的文件头信息;二是每一个字符独有的属性和位图数据。我以16*16的位图字体为例描述BDF字体文件格式。

  1. STARTFONT2.1 /*后面跟一个版本号,指出该字体文件版本*/
  2. COMMENT /*表示注释*/
  3. FONT -adobe -courier -bold -r -normal -16 -160 -75 -75 -m -160 -gb2312.1980 -0
  4. /*表示字体名*/
  5. SIZE 16 75 75 /*字符大小与在X,Y方向上的分辨率*/
  6. FONTBOUNDINGBOX 16 16 0 0 /*X方向上宽度与Y方向高度及x和Y方向上的偏移*/
  7. STARTPROPERTIES 16 /*设置字体的属性项目数*/
  8. FOUNDRY "Adobe" /*字体的制造厂家*/
  9. FAMILY_NAME "Courier" /*字体的变种字型*/
  10. WEIGHT_NAME "Bold" /*字体的印刷权*/
  11. SLANT "R" /*字体字型的设计情况*/
  12. SEWINDTH_NAME "Normal" /*字体的缩放因素*/
  13. ADD_STYLE_NAME "" /*唯一的标识该字体,一般为空*/
  14. PIXEL_SIZE 16 /*依赖于设备的字体尺寸*/
  15. POINT_SIZE 160 /*设计字体的实际尺寸*/
  16. RESOLUTION_X 75 /*设计字体的水平分辨率*/
  17. RESOLUTION_Y 75 /*设计字体的垂直分辨率*/
  18. SPACING "m" /*指出字符宽度是定长还是可变*/
  19. AVERAGE_WIDTH 160 /*字体中所有字符的平均宽度*/
  20. CHARSET_REGISTRY "gb2312.1980" /*字符集名*/
  21. CHARSET_ENCODING "0" /*字符集编号*/
  22. FONT_DESCENT 0 /*基线下的高度*/
  23. FONT_ASCENT 16 /*基线上的高度*/
  24. ENDPROPERTIES /*属性项设置结束*/
  25. CHAR 6775 /*字体文件中的字符数*/
  26. STARTCHAR 啊 /*字符起始标志及名称*/
  27. ENCODE 3021 /*X服务器在存取该字符时使用的编码。如汉字国标码*/
  28. SWIDTH 1000 0 /*X和Y方向上的逻辑宽度和高度*/
  29. DWIDTH 16 0 /*字符在x和Y方向上的设备单位宽度*/
  30. BBX 16 16 0 0 /*字符边界框的宽度,高度以及偏移*/
  31. BITMAP /*字符的位图的信息起始标志*/
  32. 0000 /*字符位图*/
  33. 04a0
  34. ……
  35. 0590
  36. ENDCHAR /*字符结束标志*/
  37. STARTCHAR 阿 /*第二个字符开始*/
  38. ……
  39. ENDFONT /*BDF字体文件结束标志*/

(3) QPF字体简介

QPF格式的字库是仅用于QT/Embedded的不可缩放的字体,在程序运行过程中,对TTF格式的字体,在第一次装入使用时,都要以给定的字体大小进行处理;而对于BDF字体,当其使用时,所有字体都必须被处理;而对于QPF字体,均以相同格式的存储。所以在字体显示时,Qt只要读取字体,做相应分析,然后显示就完成了,这样进一步减少了对RAM资源的浪费。QPF字体是基于UNICODE编码的,这为QT/Embedded良好的可移植性奠定了基础。有关QPF更详细的资料可以查阅参考文献[5]。

2、如何从TTF字体文件转成QPF字体文件

(1)把TTF转换成BDF

尽管不推荐使用TTF格式的字库,但由于TTF格式的字库可以转换成任意大小的BDF字库,而可以找到的BDF字库都是固定大小的,因此在实际制作QPF字体文件时,还是需要TTF格式的字库。把TTF转换成BDF的方法如下:

  1. ./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以升序排列。

  1. Type Name Description
  2. ULONG  tag 4字节的标识
  3. ULONG checkSum 表中的CheckSum
  4. ULONG offset TrueType font文件的起始偏移量Offset
  5. ULONG length 表长

还有一个有关Offset表的信息,包括版本号,表的数量,查找范围。入口选择,转换范围。

通过操作文件表,将描述表中的数据取出来,按照BDF字体所定义的格式写入,就可以生成对应的字体。比如,可以给出一小段c语言程序,此程序用于计算当前CheckSum的位置。

  1. ULONG
  2. CalcTableChecksum(ULONG *Table,ULONG Length)
  3. {
  4. ULONG Sum = 0L;
  5. ULONG *Endptr=Table+((Length+3)& ~3)/sizeof(ULONG);
  6. while(Table<EndPtr)
  7. Sum += *Table++;
  8. return Sum;
  9. }

利用此程序可以将每个字体的信息分开,并将每个字体信息从文件中取出来,对每个字体进行操作。在从TTF转到BDF过程中,仅通过使用WINDOW的函数是很不方便的,最方便的办法是使用c语言对字体进行操作。我在此列出转换过程中最重要的几个值:PIXEL_SIZE,POINT_SIZE,RESOLUTION_X,RESOLUTION_Y,FONT_DESCENT,FONT_ASCENT,SWIDTH,DWIDTH,BBX。这些值决定着最后生成的BDF字体与TTF字体的失真度,因为TTF是可缩放的,而BDF是固定大小的,所以在转换过程中一定会出现失真的情况。

(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(分号;)的字模到目标文件。

(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字体,不过最好不要这样做,因为失真太大。

小结:Qt 字库移植并能显示中文 (下篇)的内容到这里就介绍完了,经过本人对字库进行上述处理后,就可以在嵌入式开发板上显示各种字体,只要找到给定TTF或BDF的字库,如果找不到BDF字库,可以找到字库,然后通过TTF2BDF这个程序来得到BDF字库。这样在开发板上可以显示行书,楷书等字体,并且字体显示也很正常,不会出现大小不一致的问题。但是,本人认为,由于这是嵌入式开发,存储资源非常有限,如果能进一步将字库缩小,只留下程序中所要用的汉字组成的字库就好了,这是需要下一步研究的方向。最后希望本文能帮你解决问题。

http://blog.csdn.net/liuguangzhou123/article/details/7513652

时间: 2024-09-29 17:51:49

解析 Qt 字库移植并能显示中文 (下篇)的相关文章

Qt学习笔记-嵌入式qt程序支持显示中文

移植后得qt程序在开发板上运行时无法显示中文. 拷贝windows中的字体也不行. 从网上找到方法. 添加以下代码:需要头文件  #include <QTextCodec> QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); //支持Tr中文 QText

Qt学习之路【1】:QT显示中文问题

最近,公司项目的GUI界面使用的是Qt,研究了近两个月的Qt发现中文显示确实是一个问题,这个问题中主要存在两方面的问题: [1]中文显示: [2]中文乱码: 其中[1]问题出现的情景是:Qt的界面只有英文字母,中文一个都不显示,也不会出现乱码:[2]问题出现的情景是:Qt界面本来显示汉字的地方全部被乱码所代替. [1]问题产生的原因是:Qt字库中没有相应的字体,提供给Qt的界面 [2]问题产生的原因是:中文编码转换的问题. 字节顺序标记(BOM) 出现在字节流的开头,在windows下保存UTF

解决linux/Ubuntu下Qt creater 界面程序在编译运行后无法显示中文或中文乱码问题!

本文解决的主要是界面程序编译运行后无法显示中文的问题,如果在creater 中无法输入中文,下载个IBus或者搜狗之类的中文输入法即可解决! 首先说乱码问题,这个很好解决: 如果是在linux下打开Windows下的项目出现乱码,选择编码为"GB2312"即可! 现在主要来说说程序运行后无法显示中文或者出现乱码的情况,被这个问题困扰了很久,网上看了很多资料贴子都没有解决,所有该添加的都添加了都没办法, http://bbs.csdn.net/topics/390610841?page=

Qt使用MSVC编译器不能正确显示中文的解决方案

用VisualStudio做为IDE,使用Qt框架,显示中文,会出现乱码的情况. 原因:MSVC编译器虽然可以正常编译带BOM的UTF-8编译的源文件,但是生成的可执行文件的编码是Windows本地字符集,比如GB2312.在可执行文件中,字符串是以GB2312编码的,而可执行程序执行到该语句时,对这个字符串却是以UTF-8解码的,这样就会出现乱码. 解决方法有两种: 1.使用QStringLiteral()宏封装字符串,但此种方法不能使用tr()函数用于翻译字符串. QString str =

Cocos2d-x项目移植到WP8系列之八:CCLabelTTF显示中文不换行

在wp8平台上,CCLabeTTF显示中文不会自动换行,看了下源码,原来底层的实现是根据text的空格进行判断的,每遇到一个空格就判断是否超过label的宽度,超过就换行,但text如果是中文的话,哪来的空格给换行~~ 以下实现全部参考 http://blog.csdn.net/hopingwhite/article/details/38414917 ,整理后的代码如下: 在CCFreeTypeFont.h里的CCFreeTypeFont类添加两个方法: FT_Error addLine(con

Qt编写可换肤的中文双拼汉字输入法

时间过得真快,不知不觉已到2015年,农历春节一眨眼就过去了,端正状态收拾心情整装待发出发. 曾经有段时间,我有一个很执着的梦想,我要导演出一部空前绝后的巨幕.不过现实无情地碾碎我的梦想,也同时将我推进了人生的低谷. 我开始思考,思想很多很多我以前总是回避的问题,在一次次思考中,我能感觉到我正在向一个陌生的地方走去,前途是光是暗也无法推测,我发现我在赌,赌注是一辈子的懊悔或是郁郁终生. 但当我看到阳光弥漫在我身边时,才发现以前的我是那么幼稚,我始终在找借口或不是借口的借口推卸掉与生俱来的责任,在

Qt on Android:让 Qt Widgets 和 Qt Quick 应用全屏显示

Android 系统版本很多,较新的 4.4 ,较老的 2.3 ,都有人用. Qt on Android 开发的 Android 应用,默认在 Android 设备上是非全屏的.而有些应用的需求是全屏显示,比如游戏.那么怎么样才能做到这点呢? 请给我的决赛文章<Qt Quick 图像处理实例之美图秀秀(附源码下载)>投票,谢谢. 我们需要分 Android 系统版本来说. Android 2.x 对于 4.0 以前,比如 2.2 . 2.3 的系统,可以修改 AndroidManifest.x

WordPress英文主题不显示中文的原因:Cufon字体特效

经常会有WordPress英文主题不显示文章标题,其原因是英文主题设计者喜欢用Cufon字体特效,从而导致中文无法显示,Cufon字体特效js代码主要是将文字以图片的方式显示出来,但是其缺点是:只支持英文字符和数字,其他文字只能和他说拜拜了,中文也不例外,下面我们看看Cufon字体特效究竟是何方神圣. 什么是Cufon? Cufon 是一个用来替代 sIFR 框架,实现在网页中对文字字体进行渲染功能的纯 JavaScript 开源类库(cufon-yui.js). 为什么要用Cufon 在web

raspberry pi 如何汉化显示中文

1 树莓派初装系统之后,首次启动会出现“raspi-config”工具,如下图:(若不是初次启动,在命令模式下,请输入 sudo raspi-config 命令,即可调出此界面.若在图形桌面下,打开桌面的 LXT 客户端,输入 sudo raspi-config 命令也可以调出这个工具. 2 1.如上图,通过键盘上下键,将蓝条,移动到第 4 步“Internationalisation Options”,回车进入,会出现下图: 3 2.如上图,“Change Locale“,就是汉化的选择项:选