Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3518789
  • 博文数量: 864
  • 博客积分: 14125
  • 博客等级: 上将
  • 技术积分: 10634
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-27 16:53
个人简介

https://github.com/zytc2009/BigTeam_learning

文章分类

全部博文(864)

文章存档

2023年(1)

2021年(1)

2019年(3)

2018年(1)

2017年(10)

2015年(3)

2014年(8)

2013年(3)

2012年(69)

2011年(103)

2010年(357)

2009年(283)

2008年(22)

分类: C/C++

2010-12-27 09:47:36

2.1:SDL本身可以显示中文吗?

        SDL的扩展库SDL_ttf本身具备显示中文的功能吗?网上很多观点,说不能显示的,甚至做了分析解释了原因。但是,事实是,SDL本身就可以显示中 文。如果我们看看SDL_ttf.c的源代码,我们可以看到,最终用于构建SDL_Surface平面的函数,在三种显示模式(Solid, Shaded, Blended)下,都是其对应的TTF_RenderUNICODE_Xxx()函数。我们以TTF_RenderUNICODE_Blended() 为例:
SDL_Surface *TTF_RenderUNICODE_Blended(TTF_Font *font, const Uint16 *text, SDL_Color fg) 
可以看到,Unicode码是通过Uint16的数组传递的。在官方文档中,采用这样的形式:
// Render some UNICODE text in blended black to a new surface
// then blit to the upper left of the screen
// then free the text surface
//SDL_Surface *screen;
SDL_Color color={0,0,0};
SDL_Surface 
*text_surface;
Uint16 text[]
={'H','e','l','l','o',' ',
               
'W','o','r','l','d','!'};
if(!(text_surface=TTF_RenderUNICODE_Blended(font,text,color))) {
    
//handle error here, perhaps print TTF_GetError at least
else {
    SDL_BlitSurface(text_surface,NULL,screen,NULL);
    
//perhaps we can reuse it, but I assume not for simplicity.
    SDL_FreeSurface(text_surface);
}
请注意对Uint16 text[]的定义,既然是Uint16的数组,也意味着我们可以直接用数字作为这个数组的元素。

2.2:获得字符串的Unicode码

        SDL的不能正确显示中文的问题,首先出在SDL_ttf没有提供正确渲染中文的函数,或者再精确点说,没有提供正确渲染GB2312码的函数。 SDL_ttf提供了渲染UTF-8的函数,但是很不幸,汉字信息并不是通过UTF-8传递给程序的——即使是我们在po文件中指明了使用UTF-8,程 序调用的时候依然被转化成了GB2312——至少在win32下是这样。
        所以,显示中文最简单的办法——同时也是最复杂的实现,即直接给渲染Unicode的SDL_ttf函数传递汉字字符串的Unicode码。我们可以通过 MFC的函数得到,而事实上,我根本没装MFC。获得汉字Unicode的方法,一方面可以查表,另外,也可以通过工具软件查找。以下是个实用的小工具, 事实上,在以后的研究中,我一直用这个工具检验编码之间转换的正确性。
http://blog.ednchina.com/chinaluou/85656/Message.aspx
        这下就简单了。比如我们要输出“你好”,找到它的Unicode码:4F60 597D。因为SDL是通过Uint16传递Unicode的,所以,对应的数组应该写成:(别忘了最后加一个空元素表示结尾)
Uint16 text[] = {0x4F600x597D0};
这样,SDL就可以正确的显示中文了。注意:请使用支持中文的字库TTF文件。
        但是很麻烦,不是吗?我们当然希望汉字是可以自动转换为SDL可以渲染的编码,所以,研究还得继续。所有的问题总是能解决的。^^
3.1:GNU的libiconv项目

        再一次的,感谢伟大的GNU。我们需要的是Unicode码,在程序中转换,我们需要相应的库。libiconv支持许多字符集,包括我们将用到的 GB2312,UTF-8和UCS-2(Unicode)。具体的,在项目主页上有详细的说明。我们需要新学习直接用的类容并不繁多,同样的,如果你没什 么兴趣自己编译源代码,可以直接用在win32下编译好的头文件,库和动态链接库(DLL)。win32下的项目主页是:

有趣的是,作者把它作为了我们前面提到的gettext的一部分。在下载页面上,我们直接选择,同样的,我直接给出所需要的三部分文件的相关信息:
iconv.h:头文件,请在C++代码中#include进来;
iconv.lib:库文件,在编译时候使用;
iconv.dll:动态链接库,请放到exe文件能找到的路径下(通常与exe在同一文件夹下面)
        下面,我们看看libiconv的使用方法。

3.2:libiconv的演示程序
我们还是边写程序边做说明:
#include <iostream>
#include 
<string>
#include 
<iomanip>
#include 
"GNU/iconv.h"

void showHex(int x);
和showHex函数,是用来现实16进制的。我们在前面用过。
int main(int argc, char* argv[])
{
    
//src string
    const std::string str = "你好";
    
//string size
    const int STR_SIZE = 256;
    
//string to be changed
    const unsigned char* src = (const unsigned char*)(str.c_str());
    size_t src_len 
= strlen((char*)src);
    
//string after changed
    unsigned char dst[STR_SIZE] = {0};
    size_t dst_len 
= sizeof(dst);
    
//iconv's arg
    const unsigned char* in = src;
    unsigned 
char* out = dst;
    std::cout 
<< "src: " << src << std::endl;
我们用来转换的字符串是“纯中文”(为什么我要加引号重点说明,后面会有原因的解释)"你好"。STR_SIZE是预留的转换内存空间。为什么不用动态存 储呢?因为我试过,有错误,可能是iconv自身的限制。src是C风格的源字符串,dst是转换后的unsigned char数组。in和out是用于inconv的参数。
    //GB2312 to UCS-2 (Unicode)
    iconv_t cd;
    cd 
= iconv_open("UCS-2""GB2312");
    
if ((iconv_t)-1 == cd){
        
return -1;
    }
    iconv(cd, (
const char**)&in&src_len, (char**)&out&dst_len);
    iconv_close(cd); 
这一段是编码的转换,详细内容请查阅iconv的doc。
    //Unicode dst
    std::cout << "dst: ";
    
int unicode_len = strlen((char*)dst);
    
for (int i = 0; i < unicode_len; i++) {
        showHex(dst[i]);
    }
    std::cout 
<< std::endl;

    
return 0;
}

void showHex(int x)
{
    
using namespace std;
    cout 
<< hex;
    cout 
<< "0x" << setw(4<< setfill('0'<< x << " ";
    cout 
<< dec;
}
最后一部分是显示转换后代码。包括函数showHex()。

3.3:iconv的问题。

        我们似乎已经解决问题了。但是有一个问题是,这样转换的编码是8位的,即unsigned char,而SDL需要的是16位的,即Uint16;第二个问题是,我说了,这是纯中文,你试试在“你”和“好”之间加段英语是什么效果?结论是,转换 不能正常进行,在遇到第一个非汉字的时候,就终止了。
        问题还是没解决,研究还得继续。

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