青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Code Knight

Programming is so cool
隨筆 - 52, 文章 - 0, 評論 - 14, 引用 - 0
數據加載中……

[轉]CEGUI中的漢字顯示實現

幾日前,用 CEGUI做界面,發現無法應用CEGUI的window中setText()函數直接顯示中文。上網google一下,原來經過簡單的字符轉化可以顯示中文(偷著樂,CEGUI太方便了)。

 

方法如下(引用):http://blog.csdn.net/kun1234567/archive/2008/04/11/2282761.aspx

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)

{

     if (codepoint > d_maxCodepoint)

         return 0;

 

         if (d_glyphPageLoaded)

         {

              uint page = codepoint / GLYPHS_PER_PAGE;

              uint mask = 1 << (page & (BITS_PER_UINT - 1));

              if (!(d_glyphPageLoaded [page / BITS_PER_UINT] & mask))

              {

                   d_glyphPageLoaded [page / BITS_PER_UINT] |= mask;

                   rasterize (codepoint & ~(GLYPHS_PER_PAGE - 1),

                       codepoint | (GLYPHS_PER_PAGE - 1));

              }

         }

 

         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)

{

     if (codepoint > d_maxCodepoint)

         return 0;

 

     if(codepoint < 256)  //決定保留一張紋理放英文和字符

     {

         if (d_glyphPageLoaded)

         {

              uint page = codepoint / GLYPHS_PER_PAGE;

              uint mask = 1 << (page & (BITS_PER_UINT - 1));

              if (!(d_glyphPageLoaded [page / BITS_PER_UINT] & mask))

              {

                   d_glyphPageLoaded [page / BITS_PER_UINT] |= mask;

                   rasterize (codepoint & ~(GLYPHS_PER_PAGE - 1),

                       codepoint | (GLYPHS_PER_PAGE - 1));

              }

         }

 

         CodepointMap::const_iterator pos = d_cp_map.find (codepoint);

         return (pos != d_cp_map.end()) ? &pos->second : 0;

     }

     else //顯示漢字啦

     {

         CodepointMap::const_iterator pos;

 

         pos = d_hz_map.find (codepoint);

 

         if(pos != d_hz_map.end())

         {

              return (pos != d_hz_map.end()) ? &pos->second : 0;

         }

         else

         {

              rasterizeHZ(codepoint);

 

              pos = d_hz_map.find (codepoint);

              return (pos != d_hz_map.end()) ? &pos->second : 0;

         }

     }

}

 

void FreeTypeFont::rasterizeHZ (utf32 codepoint)

{

     int num;

     uint texsize = 512;

 

     if(d_hz_map.size() < 256)

     {

         float adv = d_fontFace->glyph->metrics.horiAdvance * float(FT_POS_COEF);

 

         d_hz_map[codepoint] = FontGlyph (adv);

     }

     else

     {

         d_hz_map.clear();

 

          ImagesetManager::getSingleton ().destroyImageset (hzImageset->getName ());

 

         hzImageset = ImagesetManager::getSingleton ().createImageset (

              d_name + "_auto_glyph_images_" ,

              System::getSingleton ().getRenderer ()->createTexture ());

 

         d_glyphImages.push_back (hzImageset);

 

         float adv = d_fontFace->glyph->metrics.horiAdvance * float(FT_POS_COEF);

 

         d_hz_map[codepoint] = FontGlyph (adv);

     }

 

     CodepointMap::const_iterator hzInter  = d_hz_map.find(codepoint);

 

     if (!hzInter->second.getImage())

     {

         // Render the glyph

         if (FT_Load_Char (d_fontFace, hzInter->first, FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT |

              (d_antiAliased ? FT_LOAD_TARGET_NORMAL : FT_LOAD_TARGET_MONO)))

         {

              std::stringstream err;

              err << "Font::loadFreetypeGlyph - Failed to load glyph for codepoint: ";

              err << static_cast<unsigned int> (hzInter->first);

              err << ".  Will use an empty image for this glyph!";

              Logger::getSingleton ().logEvent (err.str (), Errors);

 

              // Create a 'null' image for this glyph so we do not seg later

              Rect area(0, 0, 0, 0);

              Point offset(0, 0);

              String name;

              name += hzInter->first;

              hzImageset->defineImage(name, area, offset);

              ((FontGlyph &)hzInter->second).setImage(&hzImageset->getImage(name));

         }

         else

         {

              uint glyph_w = d_fontFace->glyph->bitmap.width + INTER_GLYPH_PAD_SPACE;

              uint glyph_h = d_fontFace->glyph->bitmap.rows + INTER_GLYPH_PAD_SPACE;

 

              // Check if glyph right margin does not exceed texture size

              uint x_next = m_nHZX + glyph_w;

              if (x_next > texsize)

              {

                  m_nHZX = INTER_GLYPH_PAD_SPACE;

                   x_next = m_nHZX + glyph_w;

                   m_nHZY = m_nHZYB;

              }

 

              // 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<float>(m_nHZX),

                   static_cast<float>(m_nHZY),

                   static_cast<float>(m_nHZX + glyph_w - INTER_GLYPH_PAD_SPACE),

                   static_cast<float>(m_nHZY + glyph_h - INTER_GLYPH_PAD_SPACE));

 

              Point offset(d_fontFace->glyph->metrics.horiBearingX * static_cast<float>(FT_POS_COEF),

                   -d_fontFace->glyph->metrics.horiBearingY * static_cast<float>(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)

              {

                   m_nHZYB = y_bot;

              }

         }

     }

 

     // Copy our memory buffer into the texture and free it

     hzImageset->getTexture ()->loadFromMemory (hzmem_buffer, texsize, texsize, Texture::PF_RGBA);

 

}

 

     OK,問題搞定,打完收工。試試,效果還不錯,可以洗洗睡了。特將自己的一點體會寫出來,給新手提供個捷徑,也希望高手批評指教。

posted on 2010-02-27 21:38 Code Knight 閱讀(788) 評論(0)  編輯 收藏 引用 所屬分類: GUI

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美淫片网站| 久久综合久久综合久久综合| 一本一本a久久| 欧美一区免费| 亚洲人成毛片在线播放女女| 欧美激情a∨在线视频播放| 夜夜爽av福利精品导航 | 亚洲精品在线免费| 国产精品视频xxx| 欧美国产日本高清在线| 免播放器亚洲一区| 欧美一区二区三区在线看| 欧美中文字幕在线| 99国产精品自拍| 亚洲福利视频网站| 国产欧美日韩伦理| 欧美日韩国产三级| 久久免费偷拍视频| 亚洲欧美电影在线观看| 亚洲人精品午夜在线观看| 国产精品久久久久久久第一福利| 久久五月激情| 欧美精品尤物在线| 欧美国产一区二区| 免费91麻豆精品国产自产在线观看| 在线视频精品一区| 亚洲精选一区二区| 亚洲国产另类精品专区| 久久久夜精品| 久久精品一区中文字幕| 欧美一区网站| 欧美激情亚洲综合一区| 久久国产精品网站| 午夜精品久久久久久99热软件| 亚洲欧美怡红院| 暖暖成人免费视频| 久久久人成影片一区二区三区观看| 欧美freesex8一10精品| 亚洲一区二区精品在线观看| 99香蕉国产精品偷在线观看| 日韩亚洲欧美综合| 亚洲免费观看| 老司机精品福利视频| 久久只有精品| 国产日韩视频| 黄色成人免费观看| 亚洲高清一区二| 久久av一区二区| 在线视频欧美精品| 欧美日韩国内| 在线亚洲激情| 久久精品夜色噜噜亚洲a∨| 亚洲娇小video精品| 日韩视频精品在线观看| 一区二区自拍| 在线精品国精品国产尤物884a| 国外成人在线视频网站| 亚洲天堂av高清| 欧美在线视频a| 一区二区三区.www| 欧美久久一级| 一级日韩一区在线观看| 亚洲久久一区| 欧美性感一类影片在线播放| 国产欧美一区二区精品忘忧草| 亚洲女性裸体视频| 欧美gay视频| 麻豆91精品91久久久的内涵| 伊人久久亚洲美女图片| 中文av一区二区| 99热精品在线| 国产精品毛片va一区二区三区| 韩日成人在线| 久久综合久久综合久久综合| 久久久无码精品亚洲日韩按摩| 欧美日韩亚洲系列| 国产有码一区二区| 亚洲精品日产精品乱码不卡| 久久国产精品高清| 香蕉尹人综合在线观看| 欧美日韩成人在线观看| 一本色道久久综合一区| 一区二区三区四区五区精品视频 | 欧美日韩小视频| 午夜欧美大尺度福利影院在线看| 免费日韩视频| 欧美精品日本| 在线日韩av永久免费观看| 欧美阿v一级看视频| 欧美激情综合五月色丁香小说| 亚洲午夜精品久久| 欧美黑人多人双交| 欧美日韩国产bt| 欧美伊人久久大香线蕉综合69| 久久久久久噜噜噜久久久精品| 日韩一级在线观看| 欧美一区二区三区在| 国产精品视频xxxx| 浪潮色综合久久天堂| 午夜亚洲性色福利视频| 亚洲国产精品欧美一二99| 一本大道av伊人久久综合| 精品二区久久| 亚洲少妇在线| 亚洲精品一线二线三线无人区| 亚洲欧美成人综合| 亚洲精品中文字幕在线| 欧美一区二区三区的| 亚洲午夜激情网页| 欧美成人亚洲成人日韩成人| 91久久午夜| 蜜臀久久久99精品久久久久久| 国产精品二区二区三区| 久久成人国产| 国产精品成人在线| 亚洲国产精品久久久久秋霞不卡| 国产欧美精品日韩| 99视频精品全部免费在线| 亚洲国产aⅴ天堂久久| 午夜免费久久久久| 亚洲欧美日韩国产中文| 欧美福利一区二区三区| 欧美α欧美αv大片| 激情欧美一区二区三区| 香蕉久久夜色精品国产| 欧美一乱一性一交一视频| 欧美色一级片| 香蕉久久国产| 久久男人av资源网站| 久久黄色小说| 国产欧美一级| 性色av香蕉一区二区| 亚洲欧美综合| 国产精品久久久久久久久婷婷 | 亚洲第一级黄色片| 欧美日韩精品免费观看视一区二区 | 久久这里只精品最新地址| 国产精品夜色7777狼人| 一区二区三区精品| 亚洲影视九九影院在线观看| 欧美综合第一页| 久久xxxx| 狠狠色伊人亚洲综合成人| 久久久久亚洲综合| 欧美丰满少妇xxxbbb| 国产精品xvideos88| 99re6热在线精品视频播放速度 | 国产主播一区| 久久久久久久久久久久久久一区 | 久久香蕉精品| 亚洲电影免费观看高清完整版| 亚洲国产一区在线| 午夜精品视频在线观看| 久久av一区二区三区| 一区二区三区自拍| 你懂的国产精品永久在线| 欧美一区二区三区免费视| 国产亚洲女人久久久久毛片| 91久久国产自产拍夜夜嗨| 99一区二区| 国产精品专区h在线观看| 亚洲人体偷拍| 亚洲视频第一页| 国产欧美另类| 猫咪成人在线观看| 一区二区日韩欧美| 亚洲精品一线二线三线无人区| 国内精品免费在线观看| 午夜精品在线看| 欧美成人中文| 亚洲一区二区三区在线看| 国产一区深夜福利| 欧美国产精品专区| 亚欧成人精品| 亚洲精品乱码久久久久久| 久久国产精品黑丝| 亚洲视频电影图片偷拍一区| 一色屋精品视频免费看| 欧美日韩午夜视频在线观看| 久久精品亚洲国产奇米99| 亚洲综合国产精品| 在线观看日韩www视频免费| 欧美日韩免费高清一区色橹橹| 性欧美在线看片a免费观看| 亚洲国产日韩一级| 久久午夜视频| 午夜精品久久久久久久99热浪潮 | 久久久www成人免费无遮挡大片 | 欧美大香线蕉线伊人久久国产精品| 亚洲视频视频在线| 亚洲国产成人午夜在线一区| 久久精品一级爱片| 午夜精品在线看| aa亚洲婷婷| 亚洲人成艺术| 亚洲国产美国国产综合一区二区| 国产欧美日韩在线视频| 国产精品电影网站| 欧美亚洲成人精品| 欧美午夜电影网|