OGREFont的研究与OGRE的中文显示

很久没写文章了,主要是人太懒了:-)
前面只发了一篇文章“汉字、图形,Zebra打印机完全解决方案”,不少人看了以后和我联系过。对于大部分人我都做了回复,希望对大家有些帮助。对于那些上来就直接要代码的,我只能说你太没有技术含量了:0)
言归正传,3周前公司开始为一个新的项目做调研。我们想把原来的一个产品(非游戏)从2D移植到3D,所以调研的对象是3D引擎。刚开始的几天,我们眼花缭乱的看了N个3D引擎,有开源的,有商用的,最后感觉最合适的还是OGRE。(IRRILICHT在最后被淘汰了,有机会我会写一篇OGRE与它简单的对比)
OGRE最吸引我们的还是它的设计和专注于Renderer的方式,关于它的特点我就不多介绍了,OGRE在国内还是用的很广的,有很多中文的文章,大家可以看看。
没想到,刚用OGRE没几天,就碰上个大问题,显示中文。google了半天,也没什么好结果。直接用D3DFont或Windows GDI也不是不可以,可惜效率太差了,不甘心啊,谁让我喜欢较真呢。那开始研究OGREFont的源代码吧。
相信大家现在在3D中显示文字都用truetype了吧?OGRE是支持truetype的,怎么支持的?当当当当,请大家鼓掌,热烈欢迎freetype。这个咚咚非常好用,而且它是完全免费的。虽然我们国内的opensource土壤还很贫瘠(比起国外的程序员来说大家都好穷啊,好不容易写点代码还希望能换几个钱来还信用卡 :-0)。但当我真的进入并了解OGRE、Freetype、zlib等opensource项目的时候,我才真的觉得当你免费得到时候很快乐,而当你免费付出时更快乐。因为在付出的时候,你会得到更多。
好了又扯远了。OGRE支持truetype的做法是这样的:由freetype获取文字Glyph,然后再Render到font texture,最后显示出来。好像挺简单啊。是的,但仅限于英文。对中文(也包括日文韩文等)的支持很有限。。。好像我还没看到有好的方法。就连OGRE的老大sinbad也承认这不容易。有兴趣的可以去看看我在OGRE论坛发的帖子。http://www.ogre3d.org/phpBB2/viewtopic.php?t=43787&sid=a7d59e0908680c28b337cc21cdde4fec(在研究OGREFont的过程中我发现了一些可以改进的地方)

原因是什么呢?只能说是因为中文太博大精深了:-)。显示英文所需要的Glyph掰着指头也能算清楚(ASCII那几个),中文可就不一样了,常用的也有近4000,这需要多大的texture啊。加上次常用和很少用的,要2万开外了(simsun里有2.2万多个)。我看到网上有的人把unicode中文范围内所有的codepoint加到OGRE的配置文件中,疯了,估计启动都要半天,而且OGREFont只支持单一的texture,尺寸怎么也要2048X2048了吧?估计字体还不敢设很大的尺寸和分辨率。

怎么办呢?我首先想到的是多个font texture,可是然后呢?难道要把2万多汉字在启动时全部载入?这显然不和逻辑。就算是一个即时chat系统,也不一定会用到那么多汉字。看来随需生成font texture才是最好的解决方法,效果肯定没问题,但速度怎样呢?大概测了一下freetype从load glyph到hinting到render至256位灰阶bitmap的速度还是很快的。在一台P42.8老机器上跑debug模式也在也用不了1毫秒(不知道有没有方法可以更精确)。好了,方案确定了,下面开始干活吧。我打算写一个自己的Font类,使用freetype随需生成texture,并在生成时加上格式。

请大家期待下一篇文章 - freetype2攻略

 

顺便说一下,这个FPS我是程序里限定在30以下的,并不是性能问题。

 

文字是人类文化最重要的组成部分

作为改变人类的IT行业,对文字的数字化、信息化的研究更是从未停止过。

如果你不知道Digital Typography,至少听说过true type或unicode这些词汇吧?

前者是一种文字技术,而后者则是一种文字编码。当然现在有一些更新的东东,如Clear type和UTF。

建议大家可以先去了解一下这些背景知识。

若论应用最多最广的文字技术,那么肯定是true type了,true type是Apple在1991年第一次推出的,

应用于当时的system7操作系统。然后MS取得了授权,并重写了光栅化程序,在1992年的windows3.1

中开始使用。为什么引入true tpye?之前的系统用什么显示文字呢?

没错,你猜对了,在true type之前,每个字都要对应一个位图(现在有的游戏也还在用),等一下,

不光是每个字,是每个字的每种格式和尺寸(也就是说,一个‘我’字从12号到20号字需要不同的

图形)。对于那个时期的硬件来说,这种做法是不能接受也没有前途的。那么true type的原理是什么呢?

简单来说,就是制作字体的人需要先将字体的上一些重要的点存储起来,在显示的时候根据不同的尺寸

和格式的要求再用这些点生成目标文字。所以true type文字是向量的,也就是说,只需要一套字体,

你就可以生成N个大小的文字。

制作一个truetype字库,对于英语这样由有限个字母组成的文字来说,只需要制作字母+标点就可以了。

但是对于中文、日文、韩文这些语言,由于文字非常多(基本上会用到的汉字有2.2万个),所以制作一个

truetype字库所需要的时间和人力会成百倍的增长。你可以打开Windows的Font目录看看,一般英文字库

也就是2、3百K,而中文的至少要2、3M。还记得方正告暴雪字库侵权的事吗?其实我是挺能理解方正的。

制作字库的苦差事我们就不管了,下面开始介绍怎样显示TTF字库。我们的主角freetype2登场了。

Debian、Ubuntu、GTK、Qt、OGRE......这些软件都是用freetype2作为font service,如果你手头有个PSP

游戏机或是Nokia的手机,那么你也在使用freetype。不是我搞个人崇拜,对于freetype的创始人David Turner

我只能说,我对你的景仰,犹如滔滔江水。。。。。。

我崇拜的是他能够坚持10几年将开源的freetype发扬光大。就算后来他去Google了freetype也在继续。

freetype的使用是非常简单的,我这里就不具体介绍了,大家可以去freetype.org学习一下。

下面我会介绍一些需要注意的地方和我的一点心得。

我花了3天时间写了一个DEMO,如下图

这个例子使用freetype2.3.7,根据设定的格式将输入的文字生成一个texture image,为真正的应用做准备。

上面是使用宋体生成竖排,从右至左阅读,右上对其的“早发白帝城”。文字大小是18px。

1). 大家可以注意一下右上角的message,看到了吧,simsun一共有22141个Glyph。

2). 每个EM的单位数量是256个,我看了simhei也是256,但一般的英文字库都是2048(都是2的n次方)。多说一句,所谓的EM

就是一个假象的方块,在这个方块内绘制文字的Glyph,(但是文字也可能超过EM的边界)。它的计量单位

是Font unit,在使用freetype的时候,这个font unit、26.6格式、point大小和pixel大小要搞清楚哦。

自然,每个EM的单位数量越多,制作字体的时候就可以越精确。但真正的输出结果却还和其他很多因素有关。

大家可以去看看,微软雅黑每个EM的单位数量是2048,这个字库在小尺寸的文字显示上效果还是不错的。

3). 2 char maps,这个是文字编码与Glyph之间的对应关系,一般的TTF字库都有2个char map,一个是unicode,一个是Apple

用的Macintosh Roman。我们一般都用unicode。

4). fixed size,这个是我这次做DEMO比较重要的一个发现。之前看到很多人抱怨freetype输出20px以下的小字体效果较差,

那么看看下面这个12px的“早发白帝城”怎么样

(格式中加了下划线)没错,这个12px是simsun的fxisize,所以效果和可读性非常好。这在freetype中也叫bitmap strike。

5). underline position是文字的下划线位置,注意,单位是font unit。

(未完待续)。。。。。。

(2008年9月11日)

上次写了一半,这几天把DEMO又完善了一下,加上了字体加粗(Bold)和斜体(Italic),又看了很多这方面的资料,感觉头大。

其实还想好好继续研究下去,可是项目的时间来不及了。我自己的字体类已经有了雏形,用在这个项目里应该足够了。

如果以后有时间,再回来好好研究。下面就继续再聊聊freetype。

使用freetype显示一个文字的步骤大致是这样:

1. 打开字库文件(以truetype为例 *.ttf/*.ttc);

2. 打开字库中的某个font face;

3. 得到文字与Glyph对应关系的charmap;

4. 根据文字的unicode编码和charmap获取文字Glyph;

5. Grid-fitting(或Hinting);

6. Render

7. 其他操作。。。。

8. 关闭

这里面我想说说hinting,好的hinting算法对于小尺寸文字的清晰度与可读性是至关重要的。

一个文字大概的形状通过Glyph是定义好的,但是根据尺寸缩放后显示出来的效果怎么样,hinting是最重要的一步。

一个好的hinting算法可以达到点阵字体的效果,如果hinting很糟糕的话,那么文字基本上就没法看了。

truetype针对hinting专门有opcode,也就是说在ttf文件中不光存着文字的glyph信息,还有一些用于hinting的代码

如处理‘m’glyph的时候,它的三条腿应该一样宽,如‘I’和‘T’中的竖扛应该一样宽,等等。

处理这些,需要一个解释器bytecode interpreter,遗憾的是,Apple对它拥有专利,所以使用时是需要付费的。

对于freetype1.x,所有使用的freetype的用户都需要付费给Apple。

好在freetype2.x已经不受这个限制了,因为它新增了auto-hinting模块。我记得看到David Turner说过,制作

auto-hinting模块是一件非常费时费力的工作,需要一点点去调整和优化。可喜的是,现在的auto-hinting与

anti-aliasing结合生成的文字已经足以媲美使用bytecode interpreter的结果了。

其实hinting并没有一个“最好”的结果,需要在所有的因素之间妥协,找到一个最佳的妥协点就好了。

最后送给大家一副小篆字体生成的“早发白帝城”,老祖宗留下来的东西还需要大家来发扬光大啊!

 

按计划应该直接开始说我的字体类ODText,但是最近在开发上进度比较缓慢。
首先是到季末了,在忙一些非技术上的事情。其次是还想把效果和算法做的更好一些,因此想看看别人是怎么做的。
这就有了这篇小插曲。
1. CEGUI的FONT类
在网上看到了CEGUI可以支持中文输入,这使我萌生了看看它源代码的想法。感谢Crazy Eddie :-)
不出所料,CEGUI的Font类也是基于freetype2的。字体生成的原理和OGRE一样,获取Glyph,生成texture。但是效果
和功能却比OGRE强很多,我觉得在OGRE Font中缺少的baseline,ascender等参数都有定义(看来我之前
的想法还是正确地)。在Layout的时候还可以加上格式。看到这里我曾一度觉得我的字体类已经可以仍掉了,使用
CEGUI就行了。但是接下来,我发现CEGUI的Font类居然在update的时候把一个font face的charmap中所有的Glyph都
获取并render...如果是英文字库,没问题。但如果是simsun的话,2.2万个...我没有测试,因为我觉得这样做在启动
时会很慢,如果是大字体的话,时间和空间可能都会有问题。另外,Vertical Layout, Right 2 left, bold, italic
等功能也没有。看来,车轮还是要自己造。
2. Pango
如果你的系统是Linux,那么很可能你现在看到的文字就是用Pango生成的。我觉得这是个很让我着迷的项目。先说说
它的名字,Pan是希腊语,意思是所有的,也是英语中常见的词头,go是日语中语言的意思。所以Pango的名称预示着
它可以处理所有的语言(多么美好的一件事)。它可以使用freetype2生成文字信息,render时使用Cairo,也可以直接用
Windows GDI。
郁闷的事情发生在当我试图编译它的源代码时,使用VS废了半天时间竟然也编译不了。看到它的网站上写的"Building Pango
from source can at times be a difficult process.",只好放弃了。那么就开始研究源代码吧。
(未完待续......)

(2008-09-28继续)

最近一直在忙别的项目,中国的 挨踢人 生活难啊。

Pango的源代码看了一些,说实话,很久没看到纯C的代码了,还真不习惯大片的struct和宏。

主要看了Glyph存储部分和使用freetype render的部分。如果Pango layout engine可以很容易集成的话,它确实是个不错的选择。

但是话又说回来,在3D的程序中谁需要那些复杂的功能呢?还是回头继续完成我的ODText类吧。

layout,cach glyph和sub pixel是值得我继续学习的地方。

代码中比较有意思的一个地方是,定义的很多struct中都有parent_instance,这是一个所谓的父类指针。然后该struct的实例

可以通过parent_instance调用所谓的父类的方法和成员变量。这不已经是一种OOP的方式了吗?

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/superjoel/archive/2008/09/20/2954566.aspx

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值