幾日前,用
cegui
做介面,發現無法應用
cegui
的window
中settext()
函式直接顯示中文。上網
一下,原來經過簡單的字元轉化可以顯示中文(偷著樂,
cegui
太方便了)。
方法如下(引用):
cegui
使用utf8
編碼格式。這就意味著我們可以很簡單的就顯示中文。
1、弄個包含中文的字型,在這裡我借用大多數例子裡的「c
:/windows/font/simhei.ttf
」檔案。把這個檔案拷貝到
datafiles
資料夾的
font
資料夾裡。
2、隨便照著乙個
.font
檔案,自己寫乙個
simhei.font
檔案。可以用
txt寫,然後儲存,有的朋友說需要儲存為
utf8
編碼格式,實際上是不需要的。
3、同時注意修改你載入到程式裡的
scheme
檔案,將裡面的字型檔案設定成
simhei.ttf
。你也可以繼續使用
firstwindow
這個例子,這樣的話直接修改源**裡的字型為
simhei.tff。4
、現在在程式裡進行字元編碼轉換,我拿**說明問題:
std::wstring aa = l"123
中文abc
あいうえお";
char buff[128] = "";
widechartomultibyte( cp_utf8, 0, aa.c_str(), aa.size(), buff, sizeof(buff), 0, 0);
button1->settext ( cegui::string ( cegui::utf8* )buff );
原理是這樣的,對於
utf8
來說,英文本元和
ansi
編碼在記憶體布局上沒什麼區別,都是乙個
uchar
。但是對於非英文本元,則是
uchar+uchar+uchar
。如果我們手工進行編碼格式轉換,會比較煩瑣。
比較偷懶的方法就是,我們先用
wchar(unicode
記憶體布局
,uchar+uchar+uchar+uchar)
來儲存需要顯示的字串,然後呼叫
win32api
來幫我們把寬字元轉換成
char(
多位元組字符集記憶體布局)。
這就是基本方法了,然後我們可以根據這個轉換方針,利用
win32api
隨意的轉換字元編碼格式,從而滿足程式中的各種需求。
通過此方法可以顯示中文,還沒來得急高興就發現了第二個問題:這種方法顯示中文速度太慢(顯示幾十個字需要等上7、
8秒左右)。難道沒有高效的方法嗎?
於是繼續
google(
我很懶,別人能做的事情從來不麻煩自己,懶得跟蹤**
),結果還真讓我找到了兩篇相關的文章:乙份是千里馬肝的《遊戲中漢字顯示的實現與技巧》,另乙份是免費打工仔的《讓
ogre
支援中文》。從中找到了原因:
原來在遊戲中,是將點陣字型檔或
tif字型裡的文字寫進紋理,根據需求貼到指定的位置。英文的顯示非常簡單,只有
26個字母,就算再加一些標點、符號什麼的,用一張位圖,就可以足以顯示所有的單詞了。而中文要
像處理英文那樣,把所有的漢字都儲存在一張位圖里,那麼每一種字型都要生成乙個巨型位圖。在gb2312中,一共有6000多個漢字,就算是用16*16,據說會有2.5m!(馬肝兄說的,我沒算過)
繼續google,也沒有找到解決問題的直接辦法,唉,再懶也得自己上陣了。
通過跟蹤除錯,發現了問題所在,原來罪魁禍首就是他:
const
fontglyph *font::getglyphdata (utf32
codepoint)
} codepointmap::const_iterator
pos = d_cp_map.find (codepoint);
return (pos != d_cp_map.end()) ? &pos->second : 0; }
原來cegui
根據unicode
字元的編碼順序,為每
256個字元分配一張紋理(例如編碼
0-255
存放在紋理一,編碼
768-1023
存放在紋理四)。英文很容易搞定了,那麼幾個字元一張紋理就夠了,可中文就得靠運氣了,有時顯示幾個字就要生成幾張紋理,還要將每張紋理用不需要的相鄰字填滿,勞民傷財!
發現了問題,我便按照千里馬肝的思想對函式進行了改造,將使用的文字放入一張紋理中,因為紋理最大承載
256個字,所以,當漢字超過
256個時,則將不常用的去掉,將新的字元寫入。
後來我發現漢字的引用沒有太多的規律,常用的一千多漢字出現的概率沒有那麼懸殊(廢話,要不怎麼是常用呢
!),沒有辦法很好地按照使用的頻率將漢字限制在
256個字以內,寫進紋理,就索性一旦滿了就將字全部釋放掉,重新寫入。(也需有我沒找到,還請高手指教)
**如下:
const
fontglyph *font::getglyphdata (utf32
codepoint)
} codepointmap::const_iterator
pos = d_cp_map.find (codepoint);
return (pos != d_cp_map.end()) ? &pos->second : 0; }
else//
顯示漢字啦
else }
} void
freetypefont::rasterizehz (utf32
codepoint)
else
codepointmap::const_iterator
hzinter
= d_hz_map.find(codepoint);
if (!hzinter->second.getimage())
else
// check if glyph bottom margine does not exceed texture size
uint
y_bot = m_nhzy + glyph_h;
// copy rendered glyph to memory buffer in rgba format
drawglyphtobuffer (hzmem_buffer + (m_nhzy * texsize) + m_nhzx, texsize);
// create a new image in the imageset
rect
area(static_cast
(m_nhzx),
static_cast
(m_nhzy),
static_cast
(m_nhzx + glyph_w - inter_glyph_pad_space),
static_cast
(m_nhzy + glyph_h - inter_glyph_pad_space));
point
offset(d_fontface->glyph->metrics.horibearingx * static_cast
(ft_pos_coef),
-d_fontface->glyph->metrics.horibearingy * static_cast
(ft_pos_coef));
string
name;
name += hzinter->first;
hzimageset->defineimage (name, area, offset);
((fontglyph &)hzinter->second).setimage (&hzimageset->getimage (name));
// advance to next position
m_nhzx = x_next;
if (y_bot > m_nhzyb)
} }
// copy our memory buffer into the texture and free it
hzimageset->gettexture ()->loadfrommemory (hzmem_buffer, texsize, texsize, texture::pf_rgba);
} ok
,問題搞定,打完收工。試試,效果還不錯,可以洗洗睡了。特將自己的一點體會寫出來,給新手提供個捷徑,也希望高手批評指教。
linux中漢字顯示的相關問題
最近在寫個小的ui程式,要求能夠顯示中英文,看了framebuffer相關資料後,還比較順利的實現了。但是關於漢字的顯示就有些問題了,這這裡記錄下,備查看。有些問題還沒有去深究。因為是試驗,所以我直接在 中寫了中文,這樣有以下問題 使用vim的時候,因為vim有自己的編譯碼格式,所以需要進行設定,因...
c語言實現單獨顯示漢字
include include include include include 單獨顯示漢字,顯示中文,在vs2008控制台程式中實現 int main setlocale lc all,chs wprintf l 原寬字串為 s n wtext for int i 0 iwprintf l n p...
STM32中LCD顯示少量漢字
以下程式主要針對stm32中庫函式進行操作 在lcd顯示漢字,首先需要對漢字進行取模,我們都知道乙個漢字所占用的空間大小是2b。接下來通過取模軟體對所需要顯示的漢字進行取模 注意有的取模軟體可能存在問題 在這我們要補充乙個知識就是漢字在計算機中儲存形式 輸入碼 漢字的字數繁多,字形複雜,常用的漢字有...