在做遊任務顯示中文的時候,如果任務中有太多的中文,ui的顯示超級的慢。這個問題是需要結局的,遂超找資料,看到了這位仁兄的寫的文件,覺得對我這樣的新手還是挺有幫助的,估計自己找原因再去寫**的話,也得花上一兩天的時間。有資料幫助,兩小時搞定,病對其中存在的一些小問題根據我的需要做了相應的修改。
這位仁兄的文章如下,希望也能給其他人一些幫助吧
方法如下(引用):
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,問題搞定,打完收工。試試,效果還不錯,可以洗洗睡了。特將自己的一點體會寫出來,給新手提供個捷徑,也希望高手批評指教。
CEGUI中文顯示提速
在做遊任務顯示中文的時候,如果任務中有太多的中文,ui的顯示超級的慢。這個問題是需要結局的,遂超找資料,看到了這位仁兄的寫的文件,覺得對我這樣的新手還是挺有幫助的,估計自己找原因再去寫 的話,也得花上一兩天的時間。有資料幫助,兩小時搞定,病對其中存在的一些小問題根據我的需要做了相應的修改。這位仁兄的...
CEGUI顯示中文
最近在學習cegui,想在它裡面顯示中文。在網上找了很多資料,發現這篇最好用。在使用cegui中,一直沒發現不能直接顯示中文,後來在網上偶然看到,才發現這個問題!然後在網上google了半天,自己解決了這個問題。1.找到乙個中文字型,以微軟黑體為例 找到c windows fonts目錄下的 sim...
CEGUI中文載入優化
cegui中文如何顯示這個就不說了,改下字型就ok了。對於中文載入的優化,網上最流行的說法是用一張或二張紋理儲存,當新的漢字沒有在紋理上的時候,清空紋理重新新增。對於這種方法如果漢字使用率少的話還不錯,但是如果對於不同漢字出現頻率較高的話,那麼這種方法,會出現介面一卡一卡的現象,那就是臨時清空重繪紋...