mygui中使用gdi字体
现在很多网络游戏里都使用了FreeType来显示中文字体,它可以实现很绚丽的字体效果。但是有个缺点就是加载太慢了。尤其是mygui里使用FreeType慢的让我无法接受,故打算将其字体支持增加gdi字体,以便备用吧。
程序参考了微妙的平衡(这小子最近消失了)早期的代码,hge的gdi字体。其实这种方法不光是能用于mygui,几乎dx平台下面都能用。这方面的资料也挺多的了,主要是利用一个api,GetGlyphOutline。大致说一下,该函数取得被选进指定设备环境的TrueType字体的字符轮廓或位图。这个函数的具体说明不在此粘贴,可以自己Google。
贴一张图(来自网络)来帮助理解字符轮廓:
得到字符轮廓以后,我们把它渲染到一张存在于显存上的texture上,并保存字符对应的位置信息,在用到的时候就可以通过查找的方式将其渲染出来了。为了效率考虑,字符在第一次使用的时候去加载并保存到一张大的texture上,从左到右从上到下码上去。这样做的好处是,减少渲染批次,提高渲染效率。
1.增加ResourceGdiFont类,基本的先从ResourceTrueTypeFont类改过来就可以了,主要是解析一些配置文件里的信息。
2.该类中增加loadCharactor函数,用来第一次加载字符。从GetGlyphOutline获取到字符轮廓,锁定texture,将字符轮廓信息拷贝到texture的指定位置上,然后保存位置信息。
3.初始化函数中。创建并设置DC,根据配置创建gdi字体,CreateFont。然后创建texture用来保存字符信息。
4.在MyGUI_FontManager中注册字体类型。FactoryManager::getInstance().registerFactory<ResourceGdiFont>(XML_TYPE_RESOURCE)。同样还有销毁的地方,按照TrueTypeFont的样子抄过来就行了。
5.修改字体配置文件MyGUI_Media/MyGUI_Fonts.xml。直接改成下面这样就不需要改其他文件,可以测试了。
<?xml version="1.0" encoding="UTF-8"?> <MyGUI type="Resource" version="1.1"> <Resource type="ResourceGdiFont" name="DejaVuSansFont.17"> <Property key="Source" value="宋体"/> <Property key="Size" value="19"/> <Property key="Resolution" value="50"/> <Property key="Antialias" value="false"/> <Property key="SpaceWidth" value="4"/> <Property key="TabWidth" value="8"/> <Property key="CursorWidth" value="2"/> <Property key="Distance" value="6"/> <Property key="OffsetHeight" value="0"/> </Resource> </MyGUI>
6.这样启动程序的时候就可以显示宋体字了。
7.注意代码中默认的字符texture大小是128*128,英文和符号勉强够用,到时候出错了,记得增加texture的大小。
8.总结:还有几点需要注意。GetGlyphOutline的几个参数的意义及使用;texture上字符的位置信息;拷贝字符信息时需注意;本程序对mygui的L8A8像素格式暂不支持,只支持R8G8B8A8 32位像素格式。
9.详细看代码吧(没有提供可运行的demo程序,自己将这两个文件加到mygui里稍加改动就可以看到效果了)。
PS: 2011.9.22 这几天发现使用我之前写的 mygui与hge的结合 的hge渲染mygui版本,字体有个问题。有一部分字,尤其是开始的时候没有加载的字符,后面都显示不出来。苦苦查找了好几天,最后发现原来是Texture_Lock的一个参数问题。注意红色部分。道理自然也明了了。
void* HGETexture::lock(TextureUsage _access) { if (mLock) return nullptr; DWORD* lockbits = mpHGE->Texture_Lock( mpTexture, TextureUsage::Write!=_access ); mLock = true; return (void*)lockbits; }