CEGUI中文顯示提速

2021-06-29 09:44:56 字數 3704 閱讀 8839

在做遊任務顯示中文的時候,如果任務中有太多的中文,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了。對於中文載入的優化,網上最流行的說法是用一張或二張紋理儲存,當新的漢字沒有在紋理上的時候,清空紋理重新新增。對於這種方法如果漢字使用率少的話還不錯,但是如果對於不同漢字出現頻率較高的話,那麼這種方法,會出現介面一卡一卡的現象,那就是臨時清空重繪紋...