在C++中使用freetype显示中文的问题
问题
在使用opengl渲染时,尝试使用freetype来渲染文字,但是在渲染中文汉字的时候遇到了问题,无法正确渲染中文
解决方案
直接先说解决方案,在从face中获取glyph时,使用wstring代替string或者char *,并且在渲染查找glyph时,也这么做:
1 |
|
渲染时的代码如下:
1 | void demoRender () { |
好了,freetype已经可以正常显示中文了。
排查过程
首先,我是按照 教程 来学习freetype渲染文字的。
教程原版是英文的,所以原版教程中的渲染只有基础的128个ascII码。我这边便想到了拓展到实现中文渲染。(因为在libGDX中,也是使用freetype,是可以正常渲染中文的).
于是我便写了如下的代码:
1 |
|
注意,我这里使用的是std::string,底层还是char数组.
于是,在render的时候所有的中文全部被变成了未定义的方框。
这个时候我比较好奇了,最主要的是控制台是可以正常输出这段字符串char数组的。
于是我先百度了c++ freetype 中文 等关键字,刷到了这篇CSDN文章,我意识到了,中文跟一般的英文字符不一样,中文使用的unicode,一个unicode = 2byte。
但是在c++中,char是等同于byte的。所以一个char是无法存储一个中文汉字的。
这点跟JAVA不一样,java中,char类型底层就是两个字节,所以可以正常使用中文.可能java底层的c++代码中,char使用的就是wchar
于是,我把代码中的char*换成了wchar_t,但是我首先想到的是先在控制台输出一下wchar_t,以免对项目有不必要的改动。
这一试,就出现了问题,控制台无法打印wchar_t,于是,我感觉可能是出问题了,我就去stack overflow搜了wchar 与 char之间的转换,以及如何让系统使用wchar。但是好像并没有特别好的结果。
但最后我突然想到,freetype是查找char使用方法FT_Get_Char_Index中,charcode的类型其实是 FT_ULong,是一个无符号的long,c++中long的范围至少有32位,那么我直接使用wstring中的wchar强转成long来直接放入查找可以吗?
于是我就进行了尝试,结果是OK的。
总结
这个问题其实本身并不难,甚至比较基础,但是查询过程中,由于对c++熟悉度不够,还是走了很多弯路。甚至中间曾经出现过使用nullptr的情况,这些跟java有太多不一样了。
但最后,如何在控制台输出wchar还是没有解决。
对于这个问题,我有自己的想法(猜测),那就是控制台是windows平台的,windows平台可能对底层的char进行了自己的优化,在展示时会根据char值来判断是否是unicode来进行展示,判断是unicode则使用unicode来展示,所以直接cout输出char数组是可以展示中文的。
但是对于wchar,可能windows底层并没有对其优化,想要展示还需要我们开发做一些其他工作。
至于java为什么即使使用宽字节也可以正常展示中文,我猜测可能是虚拟机(VM)底层对其进行了优化,使其能够将宽字节正确处理成unicode。
最后附上项目地址