CEGUI中的漢字顯示實現

2021-06-16 02:58:34 字數 4404 閱讀 9316

幾日前,用

cegui

做介面,發現無法應用

cegui

的window

中settext()

函式直接顯示中文。上網

google

一下,原來經過簡單的字元轉化可以顯示中文(偷著樂,

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。接下來通過取模軟體對所需要顯示的漢字進行取模 注意有的取模軟體可能存在問題 在這我們要補充乙個知識就是漢字在計算機中儲存形式 輸入碼 漢字的字數繁多,字形複雜,常用的漢字有...