概述
本文只限於 windows 環境下。
OSG 在 windows 下對中文支持已經非常的好了,但是可能很多人並不知道如何去正確的使用。為了解決這些常見的問題,還有一些基礎知識的普及。特此把 OSG 的中文相關問題集中起來說明一下。
理論基礎
一切的原點 ACSII
不管什么字符集、什么編碼,0-127的編號都是一致的。
字符集
把具體的文字映射到一個編號,所有的映射的集合就是字符集。
字符集編碼
為什么還有字符集編碼?就好比圖片,為了存儲體積或者特殊要求,你必須選擇不同的格式;如:RGB、PNG等。
代碼頁 Codepage
windows 內碼使用 UCS-2 字符集,其他所有字符集或者字符集編碼都被統一分配了一個 codepage 編號,系統會根據這個編號來自動轉換。簡體中文版 windows 的 codepage 是 GBK,編號 936。順帶一提 ANSI 是指當前系統的默認 codepage,不同語言版本的系統 ANSI 就不同。
中文顯示
中文顯示主要通過 osgText 模塊的 String 來完成。
font 文件必須是有中文內容的,你不能用 一個不支持中文字符的 font。
剩下的只有 String 的 3 種字符數據來源的問題了。
String(const std::string& str) {set(str);} 這個基本上是沒戲了;
String(const wchar_t* text) {set(text);} 這是最簡單的,不需要多余的解釋;
String(const std::string& text, Encoding encoding) {set(text, encoding);} 這種方式也可以,只是用起來很煩,需要其他轉換函數輔助處理。
中文路徑
開始很多人都會費解為什么 OSG 不支持中文路徑,原因很簡單:這完全是 osgDB::ifstream 的小問題。因為很多插件都把文件作為流來處理了所以不支持劉的插件就能正確的識別中文路徑。
簡單粗暴型
在任何實際路徑操作之前添加下面的代碼就可以讓 osgDB::ifstream 正確的識別中文路徑了。
setlocale(LC_ALL, ""); // 空字符串表示當前系統默認區域
當然你可能覺得怎么返回默認狀態呢?
setlocale(LC_ALL, NULL); // 返回值就是當前區域狀態的字符串。
當然你可以不還原,因為只是簡單粗暴的方式。
直面問題型
打開 osgDB 下的 fstream.cpp 在開頭的地方有:
#ifdef OSG_USE_UTF8_FILENAME
#define OSGDB_CONVERT_UTF8_FILENAME(s) convertUTF8toUTF16(s).c_str()
#else
#define OSGDB_CONVERT_UTF8_FILENAME(s) convertUTF8toUTF16(convertStringFromCurrentCodePageToUTF8(s)).c_str()
#endif
紅色部分原來為 s,修改后就能正確識別中文路徑了。(前提是你沒有啟用
OSG_USE_UTF8_FILENAME 這個宏;啟用它會讓問題更復雜,甚至工程編碼混亂。)
令人疑惑的是原來的 s 並沒有任何語法問題,為什么會出錯?修改后只是精確了字符集,並非是必要的。不清楚在其他系統下有沒有這樣的問題。
中文輸入法
這個話題很復雜,牽扯很多問題,有時間慢慢寫吧。
原文 : http://giskel.blog.163.com/blog/static/7166004520138384747352/