講解如何讓OGRE支持中文(二)

0.還是前言

如果你希望能看懂這篇文章,請先確定你已經看到了《讓OGRE支持中文》(http://www.gameres.com/Articles/Program/Visual/3D/OgreSupChn.htm),因爲本文是在上一篇文章的基礎上寫的,並且假設文件都已經按照上一篇文章進行了手術。但是如果你只想簡單的使用TTF字體,只要下載本文附帶的文件,重新編譯就可以了。

1.檢討

正如上回說的,我們已經實現了一個位圖的字體。但是當冷靜下來思考時,就能發現這種方法的諸多缺陷。讀入一個2048*2048的位圖,等于在顯存中保存一個2048*2048的貼圖,不說是否所有顯卡都支持這麽大的貼圖,單是每個Font字體類吃顯存的胃口,就足以令人心驚肉跳。如果定義足夠多的字體類,我想你的遊戲的配置要求,在某些方面足以超過《DOOM3》了。

而且這並不是唯一的缺陷,文字大小相對于位圖大小比例相差太大,導致浮點數的文字位置誤差很大,你可以在一個文字旁邊看到其他文字的影子。(雖然可以通過增加文字間距來解決。)還有點陣字體本身的缺陷,就是字形單一,不適合放大縮小,一些文字邊緣的馬賽克,足以熄滅任何玩家的投入感。

似乎TTF是唯一的解決之道。

2.基本知識

(1)TTF字體。

TTF是一種矢量字庫。我們經常可以聽到矢量這個詞,像是FLASH中的矢量圖形,在100*100分辨率下制作的flash,就算它放大爲全屏,顯示出的畫面也不會出現馬賽克。所謂矢量,其實說白了就是用點和線來描述圖形,這樣,在圖形需要放大的時候,只要把所有這個圖形的點和線放大相應的倍數就可以了。而且,在網站上有很多的TTF字庫可以下載,或者你可以去買一些專門的字庫光盤。然後在你發行你精心制作的遊戲時,可以順便捎上這些後綴爲。ttf的文件就行了。包括Quake這樣的驚世之作,也都是用的TTF字庫。

(2)FreeType2庫

在http://www.freetype.org,有一個FreeType的免費庫,而且是OpenSource的。它目前有2個版本:1.0和2.0.其區別在于,1.0只能讀取TTF格式的,而2.0支持更多的文件格式,在使用它之前請詳細閱讀所要遵循的Licence,以下是摘自FreeType2.0對字庫的支持列表:

TrueType fonts (and collections)

Type 1 fonts

CID-keyed Type 1 fonts

CFF fonts

OpenType fonts (both TrueType and CFF variants)

SFNT-based bitmap fonts

X11 PCF fonts

Windows FNT fonts

(3)“主體思想”

請參照炎龍工作室的《遊戲中漢字顯示的實現與技巧》這篇文章,可惜使用的是Windows API,作者千裏馬肝,上網上搜一下吧。

附帶說一句,上面兩條都是直接從這文章中剪切下來的,_<;

不要罵我啊,不知道算不算侵權呢。

3.動手術――比你想象的要麻煩

(1)

首先要告訴字體類,我們下一次渲染需要哪些字。以便字體類可以在需要的時候釋放不使用的字體。

在Font類中~

a.增加數據 bool mUsing[OGRE_NUM_GLYPHS]; 用來標記文字是否使用。

b.增加函數

inline void setUsing(std::vector<;unsigned long& caption)

{

memset(this-mUsing,0,sizeof(this-mUsing));

std::vector<;unsigned long::iterator it;

for(it=caption.begin();it!=caption.end();++it)

{

if(OGRE_GLYPH_INDEX(*it)<;OGRE_NUM_GLYPHS)

this-mUsing[OGRE_GLYPH_INDEX(*it)]=1;//標記文字爲使用

}

}

並在 void TextAreaGuiElement::updateGeometry() 中調用這個函數。

(2)

然後是修改void Font::createTextureFromFont(void);

Font類是通過void Font::createTextureFromFont(void)來把通過FreeType2分析好的英文字畫在一個2^n*2^n的貼圖上,然後再保存英文字的位置。

我們需要修改的是:

a.從函數中分離並保存畫字的FreeType2和輔助變量。我們通過一個類來保存和處理這些變量。

class TTFMsg

{

class Max//類中類,用來保存幾個"最大",

{

int nothing;//這個是用來占位的,沒意義,反正沒他就運行出錯,可能和數據對齊有關吧。

public:

int height;//文字最大高度

int width;//最大寬度

int bear;//最大空隙?

};

public:

FT_Library ftLibrary;//FreeType2用

FT_Face face;//FreeType2接口?

uint char_spacer;//文字空隙

SDDataChunk ttfchunk;//數據塊,用來保存ttf信息

FT_F26Dot6 ftSize;//FreeType2字體大小

std::pair<;uint,uint point;//在位圖上畫字的點

SDDataChunk imgchunk;//數據塊,用來保存位圖信息

bool dirty;//標記,看是否需要更新貼圖

Max max;//幾個最大

inline bool init(Font*

font) //這個是初始化函數在void Font::createTextureFromFont(void);中調用。

{

//以下都是初始化,大部分都是從void Font::createTextureFromFont(void);移植過來的

dirty=false;

if( FT_Init_FreeType( &ftLibrary ) )

Except( Exception::ERR_INTERNAL_ERROR, "Could not init FreeType library!",

"Font::Font");

char_spacer= 5;

FontManager::getSingleton()。_findResourceData(font-mSource,ttfchunk);

if( FT_New_Memory_Face( ftLibrary, ttfchunk.getPtr(), (FT_Long)ttfchunk.getSize() , 0, &face ) )

Except( Exception::ERR_INTERNAL_ERROR,

"Could not open font face!", "Font::createTextureFromFont" );

ftSize = (FT_F26Dot6)(font-mTtfSize * (1 <;<; 6));

if( FT_Set_Char_Size( face, ftSize, 0, font-mTtfResolution, 0 ) )

Except( Exception::ERR_INTERNAL_ERROR,

"Could not set char size!", "Font::createTextureFromFont" );

return true;

}

inline bool done()

{

//在Font的解構函數中調用的,本來應該調用下面兩個函數,但是不知道爲什麽一調用就出錯,不用倒沒事。

//FT_Done_Face(face);

//FT_Done_FreeType(ftLibrary);

return true;

}

inline bool getRect(Image::Rect & rect)//這個函數以後用的,是用來找到可以畫字的貼圖的空的位置

{

if(511<;point.second+max.height+char_spacer)

{

rect.right=rect.top=rect.left=rect.bottom=-1;

return false;

}

if(511<;point.first+max.width+char_spacer)

{

point.second+=max.width+char_spacer;

point.first=0;

if(511<;point.second+max.height+char_spacer)

{

rect.right=rect.top=rect.left=rect.bottom=-1;

return false;

}

}

rect.left=point.first;

rect.top=point.second;

rect.bottom=max.height;

rect.right=max.width;

point.first+=max.width+char_spacer;

return true;

}

};

上面的類定義在Font類中,在Font中增加 TTFMsg * mTTFMsg 數據,並在構造函數中 mTTFMsg=new TTFMsg;

正是修改void Font::createTextureFromFont(void);函數,主要幾點,首先是分離出很多變量和構造到TTFMsg類中了,然後是貼圖從2^n*2^n變成固定的512*512,爲什麽要這個數字呢,因爲256太小(廢話了)。能保證512*512大小的文本區不會出現不夠畫字的情況(所有英文+符號+沒有重複的漢字),這個安全區域基本上是夠用的。(什麽,你要畫滿屏幕的漢字?哪你自己看著改吧。)還有一個重要功能是,要找100個漢字,找出最高和最寬和最大空隙作參考。修改完成這個樣子了~

void Font::createTextureFromFont(void)

{

mTTFMsg-init(this);//初始化FreeType2

uint i, l, m, n;

int j, k;

FILE *fo_def = stdout;//啥意思?我看不明白

int max_height = 0, max_width = 0, max_bear = 0;

uint startGlyph = 33;

uint endGlyph = 167;

// 找英文的找出最高和最寬和最大空

英文版MDaemon Server 如何支持中文通知
大家爲了穩定都使用的是英文版的MD,可是一定發現了很多用戶收到的的通知信件都是英文的,如果直接修改模板爲中文字,那麽收到的一定是亂碼,那麽我們該如何修改使通知可以使用中文呢?步驟:1、打開MDaemon控制器2、...查看完整版>>英文版MDaemon Server 如何支持中文通知
 
如何讓Expat支持中文XML
剛剛學習使用Expat,卻發現Expat並不支持中文。後來查找相關資料,得知Expat不支持gb2312編碼格式,主要支持UTF-8編碼格式。然而我們在程序中傳遞數據時,往往是用的gb2312格式文本的,于是想找出辦法解決之,想到兩...查看完整版>>如何讓Expat支持中文XML
 
講解如何讓OGRE支持中文(二)
  0.還是前言  如果你希望能看懂這篇文章,請先確定你已經看到了《讓OGRE支持中文》(http://www.gameres.com/Articles/Program/Visual/3D/OgreSupChn.htm),因爲本文是在上一篇文章的基礎上寫的,並且假設文件...查看完整版>>講解如何讓OGRE支持中文(二)
 
以6070爲例 講解如何讓任何一個版本的MMMB都支持5140I
以6070爲例 講解如何讓任何一個版本的MMMB都支持5140I
同學新買的一個 6070 ,非要裝遊戲玩, PC 套件又限制了 JAR 程序的上傳大小,就只能用 MMMB 了 本來 MMMB 3.0 是不支持 NOKIA6070 的,下面來講解如何讓他支持 6070 。。。同樣的方法,可以使用任何一個版本的 ...查看完整版>>以6070爲例 講解如何讓任何一個版本的MMMB都支持5140I
 
WP7用戶福音 Mango系統將支持中文輸入
WP7用戶福音 Mango系統將支持中文輸入
Windows Phone 7(WP7)手機之所以在國內市場受到冷落,很大一部分原因在于其無法提供對于中文的顯示及輸入,雖然網上有流傳著一些中文插件,但至今沒有一個完善穩定的版本。而最近,從可靠來源獲悉,包括對中文的本地...查看完整版>>WP7用戶福音 Mango系統將支持中文輸入
 
PlayBook OS 2.0 照片流出,支持 Email 客戶端及中文輸入法
PlayBook OS 2.0 照片流出,支持 Email 客戶端及中文輸入法
文章分類: 平板電腦 BlackBerry PlayBook 降臨後,我們已經來過了一次評測,當時提到它其實是一部不錯的平板電腦,只是沒有獨立的 Email 客戶端、Apps 不足及沒有支持中文輸入法,令人比較難買下手。不過日前流出的...查看完整版>>PlayBook OS 2.0 照片流出,支持 Email 客戶端及中文輸入法
 
iOS 4.2(beta)登上 iPad 小試身手!(更新:支持中文輸入法)
iOS 4.2(beta)登上 iPad 小試身手!(更新:支持中文輸入法)
今天稍早蘋果釋出給軟件開發者測試的 iOS 4.2 測試版(Build 8C5901e),也是第一版支援 iPad 的 iOS 4,各位想必很好奇 iOS 4 在 iPad 上用起來是否有啥不同,蘋果有沒有針對 iPad 的特性來強化一些 UI、操作方面的...查看完整版>>iOS 4.2(beta)登上 iPad 小試身手!(更新:支持中文輸入法)
 
iCloud不支持中文 選擇英語可登錄
iCloud不支持中文 選擇英語可登錄
  【eNet矽谷動力手機頻道】iCloud雲端服務是蘋果在2011WWDC大會中重點推出的一項服務,在新版的iOS 5中內置此項服務,不過小編卻發現該服務在簡體中文模式下並不支持。    在打開iCloud雲端服務後,iPhone彈出...查看完整版>>iCloud不支持中文 選擇英語可登錄
 
觸屏滑動輸入法Swype將支持中文-業內資訊
觸屏滑動輸入法Swype將支持中文-業內資訊
  雖然觸摸屏在智能手機、平板機甚至PC都得到了廣泛的應用,但是這也帶來了新的問題,全觸屏手機在輸入時仍存在一些缺陷,虛擬鍵盤過小、沒有物理觸摸反饋等問題導致觸摸屏輸入效率並不是很高。國外有一款名爲Swyp...查看完整版>>觸屏滑動輸入法Swype將支持中文-業內資訊
 
 
回到王朝網路移動版首頁