设为首页收藏本站官方微博

【汉化资料】开源的图形渲染引擎OGRE(3) --让OGRE支持中文TTF字体

[复制链接]
查看: 2388|回复: 0
打印 上一主题 下一主题

【汉化资料】开源的图形渲染引擎OGRE(3) --让OGRE支持中文TTF字体

跳转到指定楼层
楼主
发表于 2008-10-22 16:15 | 只看该作者 回帖奖励 |正序浏览 |阅读模式

【汉化资料】开源的图形渲染引擎OGRE(3) --让OGRE支持中文TTF字体

开源的图形渲染引擎OGRE(3) --让OGRE支持中文TTF字体- p$ s# ?& L5 e+ r2 s7 K3 n
0 W$ W1 G' R5 Z1 R3 d! F8 M, [
0.还是前言
. t9 u7 f% C+ H5 V8 }. D' [6 r7 d% H( E& ]7 u# c3 M
        如果你希望能看懂这篇文章,请先确定你已经看到了《让OGRE支持中文》(http://www.gameres.com/Articles/Program/Visual/3D/OgreSupChn.htm),因为本文是在上一篇文章的基础上写的,并且假设文件都已经按照上一篇文章进行了手术。但是如果你只想简单的使用TTF字体,只要下载本文附带的文件,重新编译就可以了。
0 T/ {9 r$ w* |0 F9 C8 o4 p$ z8 ~4 B) A; J$ `
1.检讨 & Z) i! O( K$ H1 J1 M. \

5 w$ n' n; B9 m& P6 h1 W* }: {/ E        正如上回说的,我们已经实现了一个位图的字体。但是当冷静下来思考时,就能发现这种方法的诸多缺陷。读入一个2048*2048的位图,等于在显存中保存一个2048*2048的贴图,不说是否所有显卡都支持这么大的贴图,单是每个Font字体类吃显存的胃口,就足以令人心惊肉跳。如果定义足够多的字体类,我想你的游戏的配置要求,在某些方面足以超过《DOOM3》了。
& \7 b- r6 l$ e) j, ~1 u) W
% I0 I( Z$ [( d. K: j- _        而且这并不是唯一的缺陷,文字大小相对于位图大小比例相差太大,导致浮点数的文字位置误差很大,你可以在一个文字旁边看到其他文字的影子。(虽然可以通过增加文字间距来解决。)还有点阵字体本身的缺陷,就是字形单一,不适合放大缩小,一些文字边缘的马赛克,足以熄灭任何玩家的投入感。 4 Y8 ^4 w' l6 y) V! G
+ {# O1 r" R+ k8 j% d& k% U3 L
        似乎TTF是唯一的解决之道。 * U, E; u& l# M

' u: O$ J  E1 G& \2.基本知识
" c. z* J) P  J& P5 d- j; t. J' ~: c  h  a" \
(1)TTF字体。 $ ~8 g$ G0 _* D: l
: y$ v* \( G4 m  L5 F; w) B8 y7 M
        TTF是一种矢量字库。我们经常可以听到矢量这个词,像是FLASH中的矢量图形,在100*100分辨率下制作的flash,就算它放大为全屏,显示出的画面也不会出现马赛克。所谓矢量,其实说白了就是用点和线来描述图形,这样,在图形需要放大的时候,只要把所有这个图形的点和线放大相应的倍数就可以了。而且,在网站上有很多的TTF字库可以下载,或者你可以去买一些专门的字库光盘。然后在你发行你精心制作的游戏时,可以顺便捎上这些后缀为.ttf的文件就行了。包括Quake这样的惊世之作,也都是用的TTF字库。 # [& k9 |" w# a

* W* l0 E: K  E" b(2)FreeType2库
0 O$ a# ~& i2 l2 q& n; |: l5 z! B" v' w( U3 O
        在http://www.freetype.org,有一个FreeType的免费库,而且是OpenSource的。它目前有2个版本:1.0和2.0。其区别在于,1.0只能读取TTF格式的,而2.0支持更多的文件格式,在使用它之前请详细阅读所要遵循的Licence,以下是摘自FreeType2.0对字库的支持列表:
) F/ k; E& O! I/ Z
1 p' w8 q2 k: C2 ?4 Y        TrueType fonts (and collections) 3 Y+ f" }2 x, |, K* m

2 P( Z: q  ]' G        Type 1 fonts
  x8 M( n5 y% `8 h
9 E( e9 t& P8 ]; p, {8 @        CID-keyed Type 1 fonts
0 _) f6 t, ^: w2 E4 h% m- @( i2 g; P# {8 a% C
        CFF fonts ; a. M7 |0 Z' @6 q9 O

3 }: N- T6 g+ o* o: t: B* ^1 D$ [        OpenType fonts (both TrueType and CFF variants) - C: {3 B+ n2 |! n2 u# n6 p. k( x

  x) U# r1 `; Q5 S9 w& Z/ M        SFNT-based bitmap fonts % S* {) l( v# C) E) R/ Z
" h. Z$ `' O% _7 J, Q
        X11 PCF fonts
6 x) k6 W7 P$ {4 D7 _  O+ ]5 O- R" ^3 Y0 a4 T. g3 e
        Windows FNT fonts
6 C8 b! d: o& b3 [: W0 x7 j
; i$ P6 `, t+ E. K' Q(3)“主体思想” 0 N: E8 ]( h4 a% d
. x* W. X( t+ Q  ]9 `6 g
        请参照炎龙工作室的《游戏中汉字显示的实现与技巧》这篇文章,可惜使用的是Windows API,作者千里马肝,上网上搜一下吧。
$ v# H( Y9 n; g
4 T* v: n" s5 x: A8 p% N        附带说一句,上面两条都是直接从这文章中剪切下来的,>_<  不要骂我啊,不知道算不算侵权呢。 1 t* K7 Q* {1 R( a, Y: Z& l  i

+ s/ I( w1 m7 r5 ?! Y9 t, o3.动手术---比你想象的要麻烦 % C, d2 u) Y0 |4 ^
(1) ' ~% B) L- i) `: [- I
        首先要告诉字体类,我们下一次渲染需要哪些字。以便字体类可以在需要的时候释放不使用的字体。
5 h% W5 f) b, S( B/ q) {0 e# G6 j, ^& j& V5 I) X; d, I
        在Font类中~ . x/ t# i8 j5 y9 A; f: k

! u9 D: Z' F  C8 Q4 \, C) C" E        a.增加数据 bool mUsing[OGRE_NUM_GLYPHS]; 用来标记文字是否使用。 " B/ Y) b; `' v# ~
% D( z* B) O8 i# d) P6 f$ `0 J; I
        b.增加函数 ) b/ H/ m0 F% t+ r) h( p7 g" j

) Q! U, ?) y+ W" M# G" D3 ]                inline void setUsing(std::vector<unsigned long>& caption)# ^8 F1 x. I! d- \/ f, e" s

; |; ^+ |; I' s                {
9 ~# I( d3 d; P; O1 ]5 {
! E/ n0 h) l# A                        memset(this->mUsing,0,sizeof(this->mUsing));
0 ]' d) s! L! J6 s3 `# o7 p9 g$ `* L8 Y- u
                        std::vector<unsigned long>::iterator it;
" _# L8 Y( p, u# ~' d, [* v
) P. D. e- |6 W                        for(it=caption.begin();it!=caption.end();++it)
8 x2 s" W. I- K5 {0 ^
/ M4 b4 L, q9 l                        {
& Q- {8 e4 C9 j+ i) r. T. R% S% ]5 O) K: u6 y4 r
                                if(OGRE_GLYPH_INDEX(*it)<OGRE_NUM_GLYPHS)+ M& C3 l: I) b5 {7 T! ^% i. a/ F2 a6 E

* j# ^- C2 C: }( Y$ o; u. i                                this->mUsing[OGRE_GLYPH_INDEX(*it)]=1;//标记文字为使用 5 Q1 ~' F; T0 F( a" ^% ~

/ D0 B2 l# G4 d* U! e                        }3 e# h* @' F; m
8 ^9 l7 O' y" K2 {( D0 F0 @
                }
. P' |5 f% d1 b9 M" ?4 i  J% U
1 q! W& x8 J% `3 k        并在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。
! }) N0 N4 P4 K7 e, z(2) ! z. K- k9 C9 o
' R- g- W5 H/ w% E0 m- ]
        然后是修改void Font::createTextureFromFont(void);  ^. w  a. d- f; [/ h, L( P# H

0 ~! R3 t7 x. z( O9 T2 e) D9 j        Font类是通过void Font::createTextureFromFont(void)来把通过FreeType2分析好的英文字画在一个2^n*2^n的贴图上,然后再保存英文字的位置。 7 P# z# }9 B: n# l. U
9 f# m% a" s: {; R
        我们需要修改的是:
  P8 h6 L9 H9 }( |7 V: n" _5 M' q5 Y  t! L# e1 P% f5 V! x  N
        a.从函数中分离并保存画字的FreeType2和辅助变量。我们通过一个类来保存和处理这些变量。 : d: F4 O( n2 F' P8 J2 g9 j

- G$ {. A' E6 o$ `+ e        class TTFMsg( q  K& s# Z& V3 r

" X  O0 [+ ]+ z0 f                {. v1 @9 N' y3 ~+ k

% }" F5 {9 k7 s, p4 F" n                        class Max//类中类,用来保存几个"最大",9 x. g* }" `& L# O% T7 a
$ N  v7 A: \7 J: D8 X) u
                        {
; m* g" y" D" M6 C4 ?4 F9 M" H6 M' @1 O+ z9 Y- {
                                int nothing;//这个是用来占位的,没意义,反正没他就运行出错,可能和数据对齐有关吧。
! q5 i4 w8 d# l# X* a0 B' r( i. z5 L$ l& {+ ]& y% ^
                        public:
; J9 i3 N9 {4 Q" v                                int height;//文字最大高度 6 ~  b$ }) ]+ {% P0 B9 T
                                int width;//最大宽度
8 v) g! E! J& u9 R+ d                                int bear;//最大空隙?
: K, O  ?% u$ ^# G4 [                        };
3 c/ q% w/ x7 _. I1 y& o* W                public:6 B7 y  v  S$ ^4 H3 X
                        FT_Library ftLibrary;//FreeType2用 4 [* X* g9 B7 L0 l! X0 j
                        FT_Face face;//FreeType2接口? $ ?0 k/ M! b/ d! a- b
                        uint char_spacer;//文字空隙
* n# F; |7 V  Q9 K2 J/ f* L  @9 @$ U. {                        SDDataChunk ttfchunk;//数据块,用来保存ttf信息
5 v( z  ?+ d8 C4 x& g                        FT_F26Dot6 ftSize;//FreeType2字体大小
  `: |+ e2 S1 o4 q* [, U5 v                        std::pair<uint,uint> point;//在位图上画字的点 $ |, T' B( a' [' }; N# K$ {
                        SDDataChunk imgchunk;//数据块,用来保存位图信息
* \7 }9 ~; m& a+ }* D/ E1 J                        bool dirty;//标记,看是否需要更新贴图 & e+ N% n; \3 A  }. e
                        Max max;//几个最大 & A* {# @; W3 J* w
$ C9 s; R3 F) I) N
                        inline bool init(Font*  font) //这个是初始化函数在void Font::createTextureFromFont(void);中调用.
) l  C9 f' N! s% {5 B0 n* ~1 Q, N
                        {       * t5 D! Y, f/ E) J9 C# |
1 L7 P, x$ M/ e$ @( @# A
                                //以下都是初始化,大部分都是从void Font::createTextureFromFont(void);移植过来的
; V) m$ s2 ]" M; X
6 w6 C# e' P" N$ {2 n$ y                                dirty=false;, U) D: i$ [6 D! J; a+ f0 P
+ F2 z8 d5 [& ^2 x9 D/ {6 d
                                if( FT_Init_FreeType( &ftLibrary ) )0 l# p1 T7 i9 c' \. [" ]8 v2 S# {
) E' a; n) Z4 {# n- ]1 f7 o
                                  Except( Exception::ERR_INTERNAL_ERROR, "Could not init FreeType library!",
& \. [0 c+ ^& l. o# i# C7 s, \
' ^+ }. \" }0 s; j                                "Font::Font");5 j! R  ?4 R% \& o( c8 {
) n( |; J1 u' C
                0 v5 |% S* @0 X9 B* S: y( L0 ^

0 d5 F% t! @6 w2 ~- |& \9 h' o                                char_spacer= 5;
6 ]% h" A% c  G, w- F; o6 u( J  _6 [' {- X6 H! x. k( R
                                FontManager::getSingleton()._findResourceData(font->mSource,ttfchunk);) e5 p/ u. k, w1 t% T

- |6 C' M; w$ U( g                                if( FT_New_Memory_Face( ftLibrary, ttfchunk.getPtr(), (FT_Long)ttfchunk.getSize() , 0, &face ) )' ]7 M' ^3 D: C" C" e3 z

: D4 @0 X6 p; w! u4 L                                         Except( Exception::ERR_INTERNAL_ERROR,
0 J1 X. H; s1 v
0 X( w3 h* K/ Q# E3 O2 [                                        "Could not open font face!", "Font::createTextureFromFont" );
1 z# d. e- ^& U* R5 ?8 Q% [  w; T5 d. C- N- C& A
                                ftSize = (FT_F26Dot6)(font->mTtfSize * (1 << 6));  q+ Y, }) c& V$ @5 a
" s- M2 M9 e+ G  ]8 I5 a& Y; H* n
                                if( FT_Set_Char_Size( face, ftSize, 0, font->mTtfResolution, 0 ) )
5 P0 g4 [! `! f8 u8 s  a6 K
  r4 r/ w& L: |" N6 }: c                                        Except( Exception::ERR_INTERNAL_ERROR, * M, v5 _5 u* \4 W7 f

: C5 ^7 w2 J& L$ J. I8 B                                        "Could not set char size!", "Font::createTextureFromFont" );
! w4 p; t# j8 s2 _+ U. M. D3 B$ C8 D
  
- C' t# t3 B( ^- r
8 U+ c# c& p: t" ^7 j1 \5 b                                return true;4 M/ V8 g! i) v/ ^

; Y$ M9 l  i6 L! C( }! z                        }5 x; x0 V1 \( W1 d
! _0 b% I9 u0 v
                        inline bool done()+ W" [. R" x$ ^  i
7 [& |1 b9 ?: n$ s9 S2 [5 ]9 m6 F# T
                        {
+ J9 A1 L# \2 A* I# i7 ?! t/ {* x& A1 E5 L. M
                                //在Font的解构函数中调用的,本来应该调用下面两个函数,但是不知道为什么一调用就出错,不用倒没事。 % T5 h+ l8 T9 ^* V
6 G9 v" r7 P5 z6 c' j4 C  S6 Y% ]
                                //FT_Done_Face(face);
/ g) V8 }% r; \. y/ z5 z7 Z
) x) W8 D6 q$ A# w                                //FT_Done_FreeType(ftLibrary);
  s# D  N8 g3 X% z2 \
( z5 A. c: Y3 J: {4 o+ r* l                                return true;) Z8 _1 ~# A+ n2 K2 h9 \; @. t$ A

* I" X( r& d; N! C* N& {3 z5 {! ]- B                        }& E2 T1 t1 m) a$ B

1 e2 z2 S/ W1 z1 ?5 K6 U                        inline bool getRect(Image::Rect & rect)//这个函数以后用的,是用来找到可以画字的贴图的空的位置 2 t* K  B9 j  x4 R5 P
1 R/ m. S% V4 n. ^
                        {
4 d! A' c/ Y. ^0 R5 r# ?$ T% N
) U# u1 I5 Z- f2 _9 i- B                                if(511<point.second+max.height+char_spacer)9 R0 b3 x- ]5 c( _# N4 @
& N3 B4 ?7 C+ ?$ w( [0 s
                                {: `$ K7 [; c+ u* ~
: q7 ^* v9 ]# S9 X. g
                                        rect.right=rect.top=rect.left=rect.bottom=-1;
) m' v& z7 ]4 T
+ G. n. C3 n- x( _3 L" K* q                                        return false;
% \# \3 h# D/ L* y- t5 W# l* V4 D- `
, h7 \4 y7 Q0 B$ Z# p                                }
9 j$ ~) h1 p9 K/ |  a" N, J! J& q; a+ w+ h
                                if(511<point.first+max.width+char_spacer)9 X0 D. Q( \9 o' ], @* n  Z

9 @* N2 T3 L; d1 z: y                                {
/ g0 D/ B% b# D( ^  d& [( T$ s' b% C; n0 Y
                                        ; j3 D; R+ U' W8 X

6 g% \# `+ W, a. H: `                                        point.second+=max.width+char_spacer;
. Y2 D  ?" `5 }# ?, L# I- j% K- Z. z+ u5 S+ }; o) O7 A
                                        point.first=0;
8 S% B( v) d5 i8 P0 Q( g
* E. I+ w2 [$ x3 R+ Q+ u                                        if(511<point.second+max.height+char_spacer). n# u$ n; B5 Q2 E7 r
- _* H# l+ W8 ?0 i+ I
                                        {) g+ {, q2 E* L' ^- g8 K5 _
$ Q: f; d) D: k6 j$ X
                                        0 X; e; f- M5 _8 x
  P9 M8 z5 ^' x7 ~; c
                                                rect.right=rect.top=rect.left=rect.bottom=-1;
7 Q, l$ U! l. k3 v- b- A
: G0 C5 w$ `/ j/ M2 {. x                                                return false;
- n# _, K1 [. \: d
- M$ R2 e; [/ p* z$ D4 J                                        }: m  K( M! ~3 r; E; [9 h$ _

# u8 e' S4 j3 G4 k+ ^                                }& N. b9 S  `- d/ a+ l: ]8 O

2 g  ?  Z' E. |' s( f8 O( N                                rect.left=point.first;' W7 v, \; c1 z+ `/ a. e+ @0 R4 a
  |' X. v5 B/ b! Z2 E, @, s0 p
                                rect.top=point.second;% g. P% O7 N  q, a( E  `
' f, A; t5 J2 R( h4 ?
                                rect.bottom=max.height;7 p' n' K2 E; ~. W  L' Y: u

2 {4 N6 e0 Z7 B: T$ @5 L                                rect.right=max.width;
( p; j/ t7 k( \# u( ~  C' O0 m, E4 {2 F( `  r
                                point.first+=max.width+char_spacer;" `$ S5 i  H* s4 f: T1 w3 ~% C
! y; M/ \% W8 X% ]! W
                                return true;/ A! l9 Z( b( O

' J! C0 _1 n( s- I                        }
- T9 C0 a, p9 S- p& b# _/ M4 V) ^, o8 t- X5 ~
                };
+ z- T" Q5 P; y# z
4 M- H& G6 h# K0 J        上面的类定义在Font类中,在Font中增加 TTFMsg * mTTFMsg 数据,并在构造函数中 mTTFMsg=new TTFMsg;
5 ^( I& v* d% c8 H- L. _2 g+ T  e5 Y9 T) W  f
        $ g! b' Q, M# }  _4 J: |: ~
% \7 M8 a9 q6 j! \8 e3 H4 u
        正是修改void Font::createTextureFromFont(void);函数,主要几点,首先是分离出很多变量和构造到TTFMsg类中了,然后是贴图从2^n*2^n变成固定的512*512,为什么要这个数字呢,因为256太小(废话了)。能保证512*512大小的文本区不会出现不够画字的情况(所有英文+符号+没有重复的汉字),这个安全区域基本上是够用的。(什么,你要画满屏幕的汉字?哪你自己看着改吧。)还有一个重要功能是,要找100个汉字,找出最高和最宽和最大空隙作参考。修改完成这个样子了~( ^8 A0 A. d: [7 }4 h) v

% h/ g2 g( K$ d: i9 V$ E: Q) n    void Font::createTextureFromFont(void)' N2 w# _- J* H/ e/ m
: M$ i. X  ~7 g& b* |
    {. x: q. _' I; u

6 F6 r0 [2 B( ^3 s4 n& ~- R. L        mTTFMsg->init(this);//初始化FreeType2
& |; h4 h9 A) F$ L9 q! D- e# M  G; `2 B' j
        uint i, l, m, n;
! p7 r8 B. @, |  Q4 N& b( L6 t  S3 p+ e) ]( B+ a5 {' j
        int j, k;- h8 v8 q+ X  O: j) t6 }
6 X( l0 t# n" P  ?' u- ^
  
0 e# S% F, u% t% \
0 D; `/ x9 |/ O: [0 Z; i       - g( q: D3 c9 ?: L" a

# F/ y. a, X' k8 a. Q        FILE *fo_def = stdout;//啥意思?我看不明白 5 o, Q9 V  y5 j+ O
# d) r- E2 E" Z( O% [4 |
  3 F. u& ]  T1 Q, {) \

, F2 @: E5 m+ a9 V        int max_height = 0, max_width = 0, max_bear = 0;3 `; x: g5 j% e0 s. z9 a. G
! H1 b' p" k1 H& ]. V" K$ |4 b7 O; _
  
7 I0 N( ]- c- h" V& P, t6 e0 g; \
        uint startGlyph = 33;
( {! _, P( w# q! j% G# ~$ }- ^# U' @! Z
! f6 m8 i4 T6 G6 r        uint endGlyph = 167;3 Z0 k. t6 H' \3 U# G

& w& @- b. g. Z5 L' u# E  H  
: q3 [, u1 S( W! Q2 ^$ @. t, Z
, t. v% s, ?" m( |3 C, y        // 找英文的找出最高和最宽和最大空隙 4 q$ p6 G# U; x$ o. j2 Z: j

) v; ~7 e- ~! z2 I8 ?# v        // Calculate maximum width, height and bearing " c2 B: S9 D. s9 b

* `4 h7 @  {3 T+ x6 ~4 C. a" _        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )9 T2 c: A3 @1 |8 }% S6 [
2 \- I& ^+ W9 b& i+ L5 G
        {5 e" p; E) b3 l! e# Q3 P/ @5 O

1 T% ^/ p9 z! T- c            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );* t! s2 Q, z$ l5 i( n
4 [0 j4 m" x# A5 q  ]6 G( t
            //以后的 <<6和>>6都是FreeType2中的数据和我们使用的数据的转换 ! P8 O9 |8 c* g: K' w
, n/ q# ^$ w, q+ D0 z
            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )
$ v" L6 T0 t# t7 H/ [0 ?5 |3 x: `5 }/ k2 E
                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );5 X( V* L+ t5 z! d  n

0 v. K% x3 \. v6 ?* I0 q: i            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )
* D% ]# P# G. \7 u% {+ K: A' W) \# V  I3 O1 {, W  j' l: |+ O
                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;
1 @( h- S# o0 `" E, d5 B" Y$ s) c' J2 m9 Z4 b
  - ^+ h8 H- h! m

. J+ {% {6 _- {. R& n- U$ f            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)
* I! F% H/ ?6 N7 x$ f, ~3 m  m# j7 e% d( m4 @+ @- J: ^  \$ P( Q
                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
/ g% Q2 e$ k' x8 n( v" Y% h" {8 q7 D3 W
        }. t$ @8 [" i- f) f

% h# Q- {1 Y6 h; L7 b, I4 L  
8 Q% k- F3 y9 I. T
! y0 q& }7 n' P  
. j; q5 h7 A9 g5 e3 _! Y4 _$ a( a5 B, t) }. a3 J
        //下面的for是找100个汉字,找出最高和最宽和最大空隙作参考。姑且认为最的汉字就在这一百个里了。
; Q( d8 W7 {& |3 V0 ^
) ?5 ~3 |% Y$ i1 @& F        for( i = 20643, l = 0, m = 0, n = 0; i < 20743; i++ )
5 x- T( C1 i$ F  i9 p, `' f8 `
        {5 V2 P# ~: d6 I- I; Q- X
0 L- N0 S* y% t0 T
            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );" \5 O& P# u3 x! N. N
' m9 {1 R, d8 w, O1 F
  
0 V: K9 P- |5 R+ J1 P, `5 ^0 p% \8 i1 ?7 ~8 r' t9 l' m/ s
            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )
. G# t- O5 m7 z5 W% ^, b! u
' `6 ^, B8 J5 ^. k) j' \. q) r5 Y                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );
  }+ \' T: ~/ @3 I1 F+ }1 g5 ?0 e. Q2 q/ [6 u: p' `9 ^
            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )" N) G+ Y! m. K1 R+ b, K  f3 \

. v+ m7 \6 E1 w4 C3 x6 L( M6 v                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;3 l  K: P/ o- Y* g- j* [5 G

4 R! J' G# o  p' x, g9 T. B  % g" n! Z9 U4 {8 U
; E3 u# Y5 E  C* e! W/ ?
            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)  q% u1 z0 O' ^& f. @& H

* O) Y) C, X$ A4 W                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
1 R5 V) _$ e+ ]9 V/ z% c
7 F& i- q  ]/ D2 Q  
; O& r# n( s, Z, |7 l4 S3 u# B# ?7 x: E, c6 s' o0 d' U
                        
2 U6 t2 w: r# L! P& S" F. G2 G" H5 k2 j( ]/ F! l
            if( (mTTFMsg->face->glyph->advance.x ) + ( mTTFMsg->face->glyph->metrics.horiBearingX ) > mTTFMsg->max.width)2 \0 p/ K+ H5 z6 p
  T$ ]9 N% R5 r1 I6 s
                mTTFMsg->max.width = (mTTFMsg->face->glyph->advance.x  ) + ( mTTFMsg->face->glyph->metrics.horiBearingX );* k1 z6 b3 ~% m4 ]4 ]5 e& ~
( t: }$ L$ G* C5 A4 G
        }
4 D, p5 F5 c, Q0 a5 p; o0 w8 B5 p7 @9 ^  d* {4 ?7 k
  
8 g! A1 m- i2 ^: w+ y0 n
; w2 z5 e- R. g) O9 }) R' w                //下面几行行不需要了 我们要512*512
  N" V+ W* t# ]' p: E6 c
- w+ c* A- u8 y; u5 [                size_t tex_side=512;//就是这个了 512$ z" z3 a% U4 }+ ?1 b* Z
2 i8 Q8 p) t: V" B% x: G' ]# b. C
        //定义数据宽度 因为是32位的位图 四个char为一个像素,为什么要位这么大呢,难道不能用8位的么,我尝试着改来着,不过改了之后就不透明了。望高手看看能不能改。
! S; u4 x) U5 r5 m$ e! r! t
# R% c' t9 i" O1 y3 ~/ l" @1 a                size_t data_width = tex_side * 4;
1 |4 @! T! W5 P' i
# x+ y, N: K- C( L) \. ^( l  
1 H. n4 m0 O) Y& q5 x' H% s) R
$ f" v) Q* J, a' R& ^, H                LogManager::getSingleton().logMessage("Font " + mName + "using texture size " +
3 \2 h/ i* M* q
8 O$ y$ Z7 d* a' p0 i                        StringConverter::toString(tex_side) + "x" + StringConverter::toString(tex_side));
, U8 |# S, C* _0 ^# r% ?
7 {  z- U4 w& F: V9 `! [, Z, C  
& R: z5 f9 o+ M8 X3 \: Y5 s; W, }2 S8 h0 ~* S
        uchar* imageData = new uchar[tex_side * tex_side * 4];//设置一个空间用来保存位图 1 o& m$ H) K, O$ ?
- a: X+ s' \' h. e+ y% W( f9 F
                // Reset content& R- i5 _0 p. o9 O0 y: S+ e* Q
4 ?1 _; X4 x, b
                memset(imageData, 0, tex_side * tex_side * 4);//清零
& Z$ k7 B$ `& j3 q# E! F
, `9 R$ D* y, Q6 n( Z" ^1 ?- H  9 w0 ^$ k& _" h8 X2 W! ~
# e- W  }4 f. {* x( F" n
        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )//遍历每个字, + U9 F; P$ d  g" ?4 o% S

+ o7 E7 h$ ?( |: T4 e! D8 w5 k$ q0 G$ Q$ p2 T        {% j3 \- r! s5 J( j6 }% v, e5 Z

+ L+ l$ w- U& {1 i                        ) Q9 q" ^* G! A6 Z1 a

# ?: a  ?0 r3 V  T+ y  y$ l            FT_Error ftResult;
/ o+ Y7 c- h0 c2 F: }# O5 N9 W5 V- d6 F5 o9 B! _2 N
  
8 V! H$ N; T7 o7 V8 W& x
; h' [, j* E0 b5 R4 C            // Load & render glyph ! n( a% `5 s' h/ v6 D' G& p$ ]

& O" z0 x  s+ Q            ftResult = FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );//读取字体
- C. ^9 `+ q$ w7 ~( l2 v6 }- t( Q
            if (ftResult)# e  S7 l7 V# x2 Q7 \8 b3 U( q
$ I; y& c( s# A) ~
            {7 [3 N/ K, C7 H: M( F7 J

! O# O' d( s) v                // problem loading this glyph, continue
" l- @6 k, P1 @8 A! @/ d, L& v. T9 e  s; K* N0 J" p
                LogManager::getSingleton().logMessage("Info: cannot load character " +
* I$ ?( ]" n1 k+ K1 M2 b- q
: E3 W+ n, ~( `/ ]                    StringConverter::toString(i) + " in font " + mName);# U( X) r5 }2 Y; ?* T/ x

" {9 l2 p  T( x+ M( |' N8 Q                continue;//如果错误跳过 6 z, i  l- u  U% j# t  g5 |, r& ?
& A  C9 v% L- P/ v- c8 d: R& f6 H
            }. a3 r& K2 q! z
! J9 K7 ]# s8 a
  3 G, B3 i) D0 r0 T$ ^9 J

& R) C+ I" o: t: V0 v                        // 应该是字宽 ' J, g+ f( o* o5 V7 v$ P0 D1 \

$ ]& }6 f5 h3 l4 w' V, b                        FT_Int advance = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
1 Z0 V0 ^7 s) ^
% O1 J* Z4 H) ^# v* j                        ; c8 h3 Q  y) D* V
0 ]; [, ]2 B  G  S' M
                        // 得到FreeType2的位图 " E6 g  e! F8 \5 G( b/ k

# H5 R2 y' M/ u5 b; V2 K            unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;
$ z% b6 }# U- Y, }' t) r
( }, k. n1 T7 K  o: i4 j  l  
" {% @" P; T' l6 r5 l& Z! o9 ?% g% E* O1 y9 [+ I: Y1 y
            if (!buffer)
* T' ^1 U/ \" s# V, T+ m
) \- d; P/ t1 Y1 H" f* Q            {4 x# U9 Y+ ~3 j! G, B

4 {8 Z" Z* [+ x' y% q# h                // Yuck, FT didn't detect this but generated a null pointer! * Q2 s& _" s# d& \

! Z& D9 `. ?3 k& E1 `- Y8 W% L                LogManager::getSingleton().logMessage("Info: Freetype returned null for character " +2 ~9 q# r8 Z9 c/ w9 i/ |

& w  I7 ?* i& j( K% Y* \                    StringConverter::toString(i) + " in font " + mName);
% I+ n- P: A, y0 q* T% N3 u$ ]4 s8 b
6 a( i4 i) \( c6 M$ R; z; S                continue;//如果得不到跳过
; O" l6 i0 l0 H$ l7 n+ y: ~/ `6 F! b( Y; x8 ^2 A5 B. d
            }
7 o9 F/ H6 k8 g0 b7 w( x. K2 Z4 h7 D5 P
  
5 N+ [" \# @, O5 l  m/ r
0 a# ^7 i) g+ b: C- z                        // 得到y的空隙 (最大空-空-本字空)就是说空出这些字底部就平了
8 x1 \$ F' |* {
7 n4 K( @3 ]0 c$ g7 E$ O            int y_bearnig = ( max_bear >> 6 ) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );9 }1 H9 ~9 b/ n3 n( o
1 f& ?' ]" j  a' G8 N  z
                        
6 K' R7 E" C1 x3 Z* v; {! W: b9 I5 F- n1 N7 |9 y
            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ ). j  L( S5 w3 w9 j7 ?) u

1 r5 `; d. K( ]2 j* x- o            {
. J7 l$ R1 w7 z* ?$ A: Q
- c" i: G/ I! e# o/ T                                int row = j + m + y_bearnig;//相对行+本字在位图的总行+空隙 + H9 R6 I% S* e5 j6 W0 v

# i; Q4 j8 X4 U' c* k  f- M2 n                int col = l;//列
- E9 O1 O2 S4 W: k( u
/ L# m* Q6 g# q% ]0 f$ k                uchar* pDest = &imageData[(row * data_width) + l * 4];//找起点   
4 M+ M/ d; n5 @- Z8 T, q/ W. a/ n9 ?" l6 F
                for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//画图
4 B3 k% i# t  `6 V' l2 M5 i- c: z# m$ I" |, Q# W: R4 g% ?
                {% B: j, j% l1 x5 R; c
: d, U7 X- p& p8 U- s
                    if (mAntialiasColour)//看不大懂,难道是灰色字体?
6 ^% g$ t) ~- S& a! z! `8 ^+ q2 M9 E1 _' W$ K7 [0 t; t! O- h* q1 y, X
                    {( X( m7 _. S& q8 \' ]* F1 B% w

0 k3 V/ P1 s3 i# \( P) o0 D                        // Use the same greyscale pixel for all components RGBA . a- e; F" s* h- S( }

3 ~% N, x* S' G, m                        *pDest++= *buffer;
  Q+ C( u* X+ r) \; D/ `( b3 b5 @6 u8 @+ }
                            *pDest++= *buffer;
$ p6 {. {* w4 Q8 f
" m# q0 x# X# e  T                            *pDest++= *buffer;% F- r' b- a. Z& S

1 c, J4 s9 U4 U8 `8 ~% b+ h                    }8 D% _: F8 D# _& t

. o. t3 `1 q" z% X9 L                    else ' u' Y8 t# c. L1 V* t

7 O2 ?- K* G; r                    {- t' t# H# |4 V+ \* J+ {1 U
/ F1 |. m" ^% M/ L% ^2 i8 X
                        // Clamp colour to full white or off 9 t; E5 R, G3 d% e: E. x1 w8 _! `8 G: i

  ~0 ^) e& F: L' C( i, G. I                        if (*buffer > 0)
4 x& Q3 E0 l# @: N9 I7 w% J% l5 W7 t/ D% s
                        {% q2 B: O! \! G( x( S

( y: A- T1 {! R                            *pDest++= 0xFF;
4 }# |3 ^" }+ i) F; g: F. j& x" g& B7 q6 e+ C6 m
                            *pDest++= 0xFF;8 |; ~1 H) x+ R
. e3 _8 F3 Z+ X2 J/ }
                            *pDest++= 0xFF;& }8 O7 ]$ V) m% y* `" F4 p, A

) c( W: ~) [4 i' [' {6 l                        }
# b' D0 @* e, f/ ]) L! H1 f1 C$ j: }* P
                        else 8 s7 s$ t2 i0 c  f+ G4 r' ?8 c
8 R4 B& J5 m! W  `" z/ Z* _
                        {0 B$ z! T! L6 i$ u
5 O3 D7 g, ~. H1 f6 Q# U; C
                            *pDest++= 0;
6 j/ z6 T# I8 S" k# g$ |" A6 D/ O. W- c4 p$ ^+ l: m8 `4 X" N% V
                            *pDest++= 0;
" F/ o: {4 I, T3 y& v" S# r9 z3 A! T* }
                            *pDest++= 0;
0 q3 Y1 I" Z/ z6 Q& {) E! m1 B1 j. Z0 ~6 U4 n- ^4 I- J4 c
                        }+ Q% |, D9 J$ {# R5 A
2 m% r; G" p# c, Y6 p: U
                    }; g) R4 ]) k8 W% i/ t/ M7 V6 H
0 T& Q6 }8 }6 O1 p2 [3 r
                    // Always use the greyscale value for alpha ( [, y: n8 L3 H
2 {* k1 y* [# a; g: W- V- L, J! y& G
                                        ) c6 w% H2 ]7 u
/ w1 O7 {- o$ l' t
                    *pDest++= *buffer++;//alpha! 我是一点不了解了为什么是这个?   U, ~' h" i7 j  F

# T) i) g7 K# M; c- ]2 Y4 _                }
0 }  i" s  o( t- ^# J- J/ M- C) d9 _; F! c& E8 X
            }1 |& k. w- k' u; q) |( f$ I
6 y1 K' h# X5 H6 ?
  
' @% C( b9 X& F( M5 D7 U0 R
. c5 W/ s0 P5 r% y            this->setGlyphTexCoords( i,
4 p% q8 k' ]" L( o# p, E  m) ^; m1 N8 L. q7 C
                (Real)l / (Real)tex_side,  // u1
" M+ l( e$ x% G, |2 E
- g! B* u3 v( J& D. Y8 o. r                (Real)m / (Real)tex_side,  // v1
& w; v% a3 i/ v7 x
: }9 [! Z9 [, j! q; s5 `: w/ L! n# D                (Real)( l + ( mTTFMsg->face->glyph->advance.x >> 6 ) ) / (Real)tex_side, // u2
/ z8 Z) f% Y- l! N  {7 h) V: l
                (Real)( m + ( max_height >> 6 ) ) / (Real)tex_side // v21 V4 I/ W  q6 K6 I

4 A# Y6 b' F3 W' U5 |                );//设置坐标 * R( ]. {# P! x  y! K9 e: \% p
5 f8 t5 m; k  y3 l1 o6 S6 Q* H# Q
  ' |4 ?6 {1 Y$ I5 R8 C
4 n! j# ^% @6 c8 ]
            // Advance a column
/ T) A, B- s! v& ?3 R- o
% C8 \9 H/ P' c4 R/ ~            l += (advance + mTTFMsg->char_spacer);6 L5 A: L% O" o7 W2 T

& P9 G: ]3 E5 u+ z2 C0 c2 h/ ~                        //l+= 本字宽+字空
' o; N1 u5 z1 w* F% V( U  J" x) U* e+ |6 z4 Z
  
) j" x! [1 c0 `2 }9 R) |. `8 j
4 V1 E; X0 {! b* k            // If at end of row 2 u! @+ G& N7 X9 I
6 G$ B7 O" S+ R4 p- m: A
                        //如果到头容不下一个字 ! c) i, b+ _/ _* Y7 K% F
% R5 d3 R- `2 x3 @4 u2 p
            if( tex_side - 1 < l + ( advance ) )) B+ q7 D3 N- G, b- n4 n% \

, M* |$ P9 h( v3 s" W9 C            {! \! I9 l! r1 h% D7 e. Z
! ~6 b8 w: v) z( H" z5 \
                m += ( max_height >> 6 ) + mTTFMsg->char_spacer;
2 F' c% ^6 B. [4 ~
7 S7 }+ z  y. M/ D                l = n = 0;/ P. r7 I$ R5 ?" N8 h0 z- |* |
0 x* G# z/ r$ B7 Y+ O
            }
" \  r" u, W4 t  y+ q4 j' X9 R
, `% V) x3 h1 B1 z3 E  
6 _: I' [+ R: {7 w* {( t+ X  F. e/ \# g
        }: C3 a0 g- `  b
8 }" ?# f  T8 @
                // 把信息存到我们的mTTFMsg中 >_<
# w5 X- p5 B0 i2 M/ U. W: m# w1 g) u, Y8 F& K2 z
                if(l)
. _3 @" e) y3 O9 j! v8 m  `
; ^* y9 p# Z5 Q$ _                        mTTFMsg->point.second = m + ( max_height >> 6 ) + mTTFMsg->char_spacer;
/ ~. g* s3 n3 ~* r$ d7 k+ F0 r* y4 M- x7 _/ ~+ @5 g
                else
: @" Q2 s+ g+ [/ p
. P' u4 W7 _$ w8 Y. e; H                        mTTFMsg->point.second = m;* d2 w1 J1 }( R: x) I
. e* R/ l5 I& E: ]; d5 I2 W7 r& v
  
% V" N* M  d. S: q2 U
3 {, S8 @2 {) |                mTTFMsg->point.first = 0;//另起一行
7 e& {+ k* C! _' p% W! A1 i
2 u# F0 n6 v3 f& J8 k$ H8 [  ( c0 s, G' m% c- J; \

% Z3 f: E3 q5 ~( ]8 T3 j7 l                //下面是保存几个最大。 ( M" @2 v: _2 q( D3 T

/ z' \# t4 |. f                mTTFMsg->max.height = max_height >> 6;
  N$ Q% z; T' C8 \7 D
6 t% z! g9 u* m' Z3 N4 B( j8 J* l                mTTFMsg->max.bear=max_bear >> 6;
3 H% o3 [7 c% e' X4 f+ s: f2 `) G
7 O7 x4 S  n8 f2 @2 e/ V                mTTFMsg->max.width=max_width;0 K1 m: W9 d$ U3 x; }' B: j

* ]7 [4 L2 X4 Z& L  r  , |6 E7 Z( v4 {2 E6 K6 c0 L
. t0 }6 `. d3 `: Z
                mTTFMsg->imgchunk.allocate( tex_side * tex_side * 4,imageData);
# s% K2 Q# O9 Z
% r; f3 p  ^" F               
" W: e8 b$ Z0 X$ o% j
4 N4 S; v4 J; Q6 r+ n' ~                //不知道为什么要设置img这个中间变量,似乎可以直接从chunk创建贴图
9 X1 \1 g. b. n. ~( e& D7 ]) ~- ~7 K; B) o+ H6 ]- Q' e  {
        //--Image img;
, D' d, |  o5 r4 L
7 Y' |: ]) O( X$ m; e+ f/ u                //img.loadRawData( imgchunk, tex_side, tex_side, PF_A8R8G8B8 );7 d4 X' a; B: x. a' X) L
. \5 i! O5 ?1 K8 k  x* K( t7 e
  $ B/ r' X* ]8 h
3 G& r7 M4 p1 J& p7 R! m9 v
                //贴图名
- u0 Z! t7 \+ a5 m
; j& [, N$ Y3 y4 g        String texName = mName + "Texture";
1 U( O; i$ n9 v1 C* c# Q
' G& P7 U3 ]6 H: M8 m& D                // Load texture with no mipmaps 8 f! G& w( w% |; X- @: o/ }
  m. a0 e% S/ s9 J
        // 把从img创建位图改成直接从chunk创建贴图
% _5 ^+ C8 q. F, Q& }, H2 T# x( `- ]$ N
                //TextureManager::getSingleton().loadImage( texName , img, TEX_TYPE_2D, 0  );
+ R0 z. ?# c3 H7 a8 v$ N" O0 o" a
                TextureManager::getSingleton().loadRawData ( texName , mTTFMsg->imgchunk,tex_side, tex_side,PF_A8R8G8B8, TEX_TYPE_2D, 0  );
# w/ ?# w& z' P: b9 X
! N3 c0 j3 O) Y$ S3 \0 J; q! P        TextureUnitState* t = mpMaterial->getTechnique(0)->getPass(0)->createTextureUnitState( texName );
  t9 z( L; g$ X% u0 J5 o, {
0 S% A6 D. b; }+ n, d& {6 U                // Allow min/mag filter, but no mip 0 b' i& m& A" a- A. ]; B& v

2 _& Z. X5 W7 s+ e- j7 ]. r                t->setTextureFiltering(FO_LINEAR, FO_LINEAR, FO_NONE);  p# c/ j4 u# m/ k* o. ?  W

- E* b5 G/ r) S. J" H        // SDDatachunk will delete imageData % i* A! M3 G: h( L% M

# U" P# j/ F# b* L4 a% C        ) y# V. C: v6 Y: u# r0 ]! G
+ a! H4 F0 M5 D! A* W+ g
    }2 L! f1 w- w( K
7 D0 g+ o# u3 X& u1 b( e7 |1 j
        你应该对照一下以前的函数,改了很多的。
& e, K" h( ]; i8 f& `3 |
* N3 [$ [$ X: g4 B. J  + S1 H7 F1 K- W

6 y" s; p- a! U& Y/ [' w  
5 n* E6 B" c- t& c. a7 ^, k  @  X) x: a0 V9 z9 S1 k! Y, P
(3) 4 X: p; t- q/ a+ G3 j- e

- _8 J7 f# h$ a$ `& K        然后最重要的是动态的申请和画字。
" f( ^0 j( `" e: w, n
7 V+ Y7 h8 N. S( u' Q1 F        首先最重要的是我们要一个方法得到汉字的unicode码,我们用到了unicodeMap数组,提供了区位码到unicode码的转换工作,等一下提供这个表给你,好不容易从网上找到的阿,可惜这个表没有中文标点的对应,如果希望支持中文标点,就要努力找到unicode码并加进这个表了。这个表是这样的 char c[3]="邸";unicodeMap[94*(c[0]-0xa0-1)+c[1]-0xa0-1];就得到邸的unicode码,不知道为什么没有5165~5169的unicode码,是轮空么? ) j7 q4 m9 A  m. l# j

3 E- p8 v7 R6 ]) e0 i        
5 b5 u! I- f, J
7 i& |! J# f4 g7 }8 C        申请渲染(字)
1 S% V# _: @( P* |
; X9 U; g( _) Y4 K        {
: ?. T* p$ J- E7 s8 \" G" M" Z1 j6 o* J" t0 C
                if(有这个字)
0 g- v4 D4 r1 ]" g$ c: \
7 E0 v. ?# J5 u, J' @4 a" G& q                        返回位置
6 ~8 k$ r- N& W1 M7 o
7 u% p8 U7 f; {2 Y$ a                else7 b! J* z, ?" z
( J1 I  W% Z& ^. Q% Q, f
                {9 ~  L5 b; n, W( D$ _% U
% }0 S1 l% f/ g! |  I. W& O
                        if(有空间), r0 R- t. L9 b! e8 a& g9 @' R
: q3 D% L$ a: {* F5 ]
                                画字
! t. z5 B$ X( u6 X- B' W
+ E) E8 L) \/ u, q8 @                        else
5 ?+ R( y; K, Q$ a& w# C7 t. l! ~
: r! L' ?% d$ H9 W. o( k& u! N7 y+ i                            找不用的字//找不到就出错,没地方画了
, ~/ I; J, H( u  ~3 y8 i  K3 a( j# Z! f. p) T& g4 c- |  z. p
                                删除 在这个位置上画字
- y/ h. H' E* |1 r% P7 p3 J  D0 h- z
                返回位置 * `" s+ E. `1 c! ?4 {

1 L0 Y, h( B5 B# I) [3 g+ E                }
( @1 ^1 Y0 V; T0 X) q6 O* x2 r$ _) A9 Q* n  U7 G
        }
4 `# Z+ k- A- ^% \
  I  C7 l0 Y5 d8 y1 A1 o. ~        上面很直观把,大体就这个意思了,申请渲染的函数是inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )  const。去掉const改一改。得到
  I  g' y% _+ k7 X7 ^' N' m- i
- x+ s" H9 h) [* K        a.申请渲染
0 Y# k2 d: A( s5 E8 ~3 L- G& g) T, T/ c
        inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )         
' J' q1 g' \' A5 U+ l
+ P- f) p' F) O/ p( Y        {2 I' y" T7 S7 j* M  F: o
" k4 n) f6 {, k! x0 A; H7 @- x1 J
                unsigned long idx = OGRE_GLYPH_INDEX(id);. ]9 o4 z$ g5 m$ ~- e- t1 `
- k' T3 a6 L. {# [6 y# C
                if(this->mType==FT_TRUETYPE)//ttf?
# x0 T" x0 _. e6 A% Q- d
: B: i5 P$ w8 @                if(id>=161&&idx<OGRE_NUM_GLYPHS)//汉字?
4 Y* _0 W9 d6 j
7 j6 m$ P, O6 u' x3 ]                        if(!mTexCoords_v2[ idx ])//没有?' c$ f% G1 M& q# {
1 E" k# }9 R' [
                                setChar(id);//画字去 $ q) e. e' i3 p$ s, D. }2 S
9 n' L& V' ?% G: S
               D% i1 K# X3 w$ q8 j; t1 i
* j" W/ h* w5 @: e1 i
            u1 = mTexCoords_u1[ idx ];
. A- p& a* {5 ^1 W& s/ S4 W/ L9 {! k/ O8 p" [. t
            v1 = mTexCoords_v1[ idx ];% P& |. v: o0 T( O5 }

$ |3 h( |$ r( k9 E            u2 = mTexCoords_u2[ idx ];
6 r! h1 o; a0 X9 T( v1 `
9 g8 n" O+ w" p. f            v2 = mTexCoords_v2[ idx ];
: z7 n# \" T# b/ @
; h" @) \) B' P4 q        }# X" X; d. K( n* R

, V2 T, [. E" b$ y& d$ n0 K1 L        b.画字等
6 b  @- G2 |0 W* C3 m
0 z" Q5 u' a' ]        bool Font::setChar(unsigned long dwChar)
# T7 U! F  E0 v- e( M: @* I# d) e
6 z- Y% s: S0 s& {, f! n) W        {
0 C* y/ R/ m. ^! ^4 o) |6 }0 p5 @: Z6 f' l. L# K8 j1 @9 h: [
                int j,k;
4 j$ B! M7 t  j, j, [5 V  t$ w% q) E" G
                uchar* pDest;//操作数据的指针
) {4 K* @2 H3 x
: s3 |7 d6 K; \7 w7 R# P$ x+ H                mProportion=0.8;//不知为什么,总觉得中文都太扁平了,所以设置这个参数,在《让OGRE支持中文》中创造的参数 + Z. }. z: p1 O9 [& o
! k$ _) j0 ~3 [7 d5 X! a* z
                Image::Rect  rect;//画字的位置
' ^) E2 _( [7 W8 Q* \4 A1 Z8 H  {
# _; u$ }, d* _7 ~0 B0 u                if(!mTTFMsg->getRect(rect)/*回头看看这个函数吧*/)//如果得不到空位置 # L5 T4 X; `" g# E1 _
& i: n* D% Y: E* ?- Q& F: @
                {
' ?, t0 d: [+ }/ j: ]  P
8 n7 {* r4 U9 C% B                        for(int i=161;i<OGRE_NUM_GLYPHS;++i)//寻找不用的字
/ W3 w$ g- S1 j/ @) |$ Y: L6 ?6 v
0 C7 R- j% g! p1 P* s- q                        {
& n; \$ f3 W! T: V) b5 f8 S# T' G7 g% t$ p+ J7 f: a
                                if(!mUsing&&mTexCoords_v2)
9 K  O& S& j; t) f/ e- V3 N  ]# z9 E. D3 c  |+ ~' ^) b! J) M
                                {
9 t  P4 `5 T+ h- C  j9 q4 q( h( x! d/ b7 B4 Z0 T5 V
                                        // 得到坐标 ! Q$ \1 L( r8 m8 Z3 C: p

+ c: `. h0 A# a" }) f                                        rect.left=mTexCoords_u1*512;
: ~- F1 q1 M3 O" J+ p5 K5 v* O, s
                                        rect.top=mTexCoords_v1*512;
( I  z, Y/ _( h. D  P2 E& o( q' c4 q% v: K) D2 f/ @
                                        rect.bottom=mTTFMsg->max.height;9 b1 G2 `  d& k  i# ~

6 }1 f) Q4 w) t$ ^. h$ O                                        rect.right=mTTFMsg->max.width;
% |3 I1 ]8 {) `! T! \1 P. ~# D
4 Y! P' f3 i! S  ) R; u4 v; L1 U
" K- A, [! b3 c4 _, c# |7 C% f4 u
                                       
! W% d0 ?" k5 O
7 y- v& y) O& j+ ~5 x                                       
! `+ m3 M: F% U) U. ]3 T: U9 G3 V6 G) C$ j8 ?
                                  j- E4 l* g1 s. ^, E) M
( O/ w. G1 ~$ w. v
                                        //擦除(这段代码没有试验过,等做完输入的类在检查吧) 8 c; Q7 F# Q8 [" o. j

" k3 j* W& O* s, C3 e                                        for( j = 0; j < mTTFMsg->max.height; j++ )# p0 ?0 s* S- V2 N/ v6 O( L5 |

' K5 y9 ^: A! O  L9 r                                        {6 E7 h. ~( Y, w  E6 _

6 Q1 N' s& m# }% K% f6 l* h) U                                                pDest=mTTFMsg->imgchunk.getPtr();
: s4 t$ f3 J, {, g6 _! C
7 w  e# J! ^2 T6 S( o& v! E) J                                                pDest+=((j + rect.top)* (512*4)) + rect.left * 4;
6 O- L3 K7 A. w, v0 u3 E. W0 P2 K. x& r3 S6 b
                                                memset(pDest,0,mTTFMsg->max.width*4);
1 ]/ i; Y1 h  N* m0 i) e6 ^0 w# g( e4 v& ]7 W
                                        }: T+ q, g7 z7 x* H

/ O; |- J7 _7 a" P3 Z; I1 T                                        mTexCoords_u1=mTexCoords_v1=mTexCoords_u2=mTexCoords_v2=0;! N, U5 r; C' {( i& D

0 C5 S  a) x3 j; e& p' ]  ( ~" U' s& T0 p4 L" {% i

% x. l7 R8 f4 p                                        break;3 W: O, S! [; C9 p- |+ E- e
% ^5 t- p0 p- n; E3 `# `
                                }5 U. P- m6 D/ k$ w  y, w
' j, z# T1 y. F* @. u
                        }
* T2 {" w- e' E/ b3 M8 ]+ w/ K
* p6 N$ ?  V% f: r                        
8 k: Q) ^* l/ g  D8 I4 O! D+ Z
7 T* A# n$ c7 v( X/ f7 H' H7 N6 Y                        if(rect.top==-1)//啊啊啊啊啊啊啊啊啊,贴图竟然都用完了,没办法了,出错了
. W) s# D6 N; k: F; l& _+ f, v6 ?
4 h; z( v2 }; S  w0 a0 H                        {& c! W" ]9 f' q' v) L  }
! f* U* y# X6 ~
                                LogManager::getSingleton().logMessage("你太贪婪了,用的汉字太多了,这是对你的惩罚."); ' ]! o. g$ a: w& t( o

. V3 R# a( g& d8 o, j                                return false;. N# M" l! H# K6 B

1 q5 N- @! E7 l2 e* m                        }
/ v; P( E$ D+ R; w3 ]
: `; H2 \2 p( J" p; i        
$ O9 A* [% o8 i! ]; C, B% S
' B, W$ Y$ V2 Y1 q; H                }
# V6 i  i( e5 j- U- B; w) }" w
1 [3 u; X$ x" M3 t7 ~4 s                        2 K. l8 W, P6 l1 Q
# T( m# S3 B. s: W( _% [+ T' S: r
               
: V& a9 Y: P3 a, K- A
3 N0 V( [( k( W: a                  //以下画字的都是招葫芦画瓢的, $ N4 O' \4 G; G, T" R3 s- x

: d0 z% X6 E/ W6 H                  FILE *fo_def = stdout;' r' p; t' w7 J) N9 k6 q) N
# \, C: s; Z0 Q: d
                 FT_Error ftResult;
4 {- p7 V5 S2 a! {
: [: x6 T4 x, p9 W  + Z" v9 _5 T7 \9 q/ Q

* x4 V, I3 `7 B            // Load & render glyph
4 C' `8 x  _4 T  e  x7 t$ |! r) w1 I8 e& H/ ^
                  
& x1 V* V) c9 d5 j* ]: e' ]- @, ~1 D
            ftResult = FT_Load_Char( mTTFMsg->face, unicodeMap[dwChar-161], FT_LOAD_RENDER );//读取字体 6 d! u* Z+ b# y1 U8 y- V' w

7 ~: W: h; I$ `9 m            if (ftResult)
# d  I( C" g# L. Y, [) m
  @5 K. F: C9 ], ^8 l# p1 F; j0 S            {, D. U- u! Q7 I& d! E
" b0 A  y' Y# b; X2 y
                // problem loading this glyph, continue
$ W( z2 [2 t$ M: q' Z1 C3 |- k. J: Z% |
                LogManager::getSingleton().logMessage("Info: cannot load character " +
# }& J& |" ~% F8 v3 a5 P8 ^  c/ o
! t3 Z0 B4 u7 n7 w                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);
. }( h* ^- P/ }7 ]
5 `* Q( W4 P" V                return false;//如果错误跳过 ! }) ]3 v7 ]! _9 q1 z2 e, b

0 q3 G! ^$ c3 I1 m- b            }
" W. F4 z7 [: S( Y$ [/ q( ^
1 f. }6 c& X: D: d: F6 ?! I7 z  
/ d3 H3 \) f7 Y- m7 t+ j
4 b9 c$ ?. r& m7 {3 }          unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;" c# B  v' k0 z

) M; V4 S6 |/ V0 t' n6 i                  // 位图指针 + x' M% L0 @7 t! b) i

  s' K" w( k8 B8 ^, N            if (!buffer)( C- D% f! u2 V! u$ Y) G" L
1 t' ?% b9 \' ]) d: J
            {0 \, C5 s$ a% z

/ `' n& p, U; y& e5 N" @0 w                // Yuck, FT didn't detect this but generated a null pointer! ; _8 a. _; f' q9 Q, l! J0 h
. U: S# Z# N  \& T+ ~
                LogManager::getSingleton().logMessage("Info: 1111Freetype returned null for character " +
5 d7 [2 b( f1 D# W2 n. }$ o5 `: O% z! @
                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);  B* E$ |$ o. ?& Y% w. v

8 x, m+ q- i; t# g" J/ C% W9 c                return false;//如果得不到跳过
  R% l; Q2 N* B. G+ v0 s7 ?5 e/ [  R, m% j- X- p" b$ O
            }
! M$ h2 r5 s. t: L
; k2 {/ h* c8 l  5 V& n5 X, a9 }1 E* K9 c- e" U6 e

9 X* ]3 k  [4 U' y- w0 h                         int y_bearnig = ( mTTFMsg->max.bear) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );/ M  z* V9 R; P. D) v

& F" \  O6 u) U5 m/ @      
" t/ ?9 P) Y8 O2 E7 z$ P
7 A4 S! F  _. r+ K/ |! [                        
5 T! C/ w# Q+ R: W- c- I# o, V  c1 ^3 n4 d# P5 [
            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )
$ u% W3 I4 X3 ~, j- l; E
7 L7 D  \4 b. o6 H3 ^; K            {
5 l3 v4 ~6 W: j1 F7 D* D- @/ u0 u0 N4 _7 m) q6 k- D0 ?* P
                int row = j + rect.top+y_bearnig;6 D$ L7 l; N8 \$ Y7 ?7 d3 t2 |
8 L- y! w# J2 A" e1 g' w3 q! ]+ A# X
                int col = rect.left;//列
" {4 ^- H+ B+ w( S9 ]& F
) F0 s* [& @2 ^                                pDest=mTTFMsg->imgchunk.getPtr();
: Y& B- I9 Q7 C& x& m1 D4 D# A- a$ \$ `$ T2 A
  ( V! \6 L1 T3 M: _2 p, u  c

" i* X% F# k+ V0 @% u                        ' G' v% U1 F$ u7 Q$ `5 ^: P2 z& w, P
! m3 c3 W4 `4 V8 k& J) V5 J4 V
                                pDest+=(row * (512*4)) + col * 4;2 ]1 k9 u2 i' s* Q

0 Z9 z& z  r1 e3 q) P) r- }               for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//每行的点 , m- B) j& `# @4 a; z# |

" V3 \) K+ I# C1 k                {. z, p: x: Q9 o& B

) h. k" D8 \) A8 o7 S                    if (mAntialiasColour)
4 [" K- t" T0 R* q0 \
3 x5 o0 u  r" {; F; E# F/ k                    {9 t% {  j1 D/ T3 ]  J; x2 G, c
5 t# s' y. V4 ~/ k0 G
                        // Use the same greyscale pixel for all components RGBA % r2 A6 k+ \) r' j% {5 G

3 q- r% A5 q* L" x" n                                                        *pDest++= *buffer;" P- `1 I, n# h9 t

" e$ i, Q2 W- u: m" d1 _5 c7 R' I" @                            *pDest++= *buffer;) F2 R+ r9 f6 b7 T) E* ?* M7 [

! a9 z* [/ u6 V3 T; k                            *pDest++= *buffer;
" G5 }5 g+ O% S/ x2 `$ e& a4 ^" z4 b# Y
                    }
7 ], u# A0 r$ N
. c' ~3 }0 M7 v/ t. c0 J; r$ l                    else
/ y8 L/ L6 E( [% R& Y4 x- r) P- P$ }5 N' V& Y# M. n0 ^
                    {: {# P9 f& {( ~* P
# c: l* e: o6 [4 B' f5 V
                        // Clamp colour to full white or off
- T, M4 S3 {% X, U9 k
$ B# E8 G6 m4 d                        if (*buffer > 0)3 F# R5 e! k3 ~

% @# P! N2 b$ i: U                        {9 \; N3 S% [8 K7 J* I9 u) ]
" b5 g$ v: X8 y( \8 Z' e+ X
                            *pDest++= 0xFF;
# v' j3 z4 ?6 C6 }5 c( a
7 J* F9 B3 q* I9 M4 ]6 U, l2 t                            *pDest++= 0xFF;
) w# \% |6 A3 F  V3 {" A& M5 q" A7 ?& s- ]' [1 N
                            *pDest++= 0xFF;5 J" q: @) v# k% M2 y- _+ o

* ~& T+ ?6 s* J* Q/ _                        }
5 K( y: x. m" k- d6 H; k, z/ l4 d8 i- R8 r
                        else
4 c: `9 S& q+ S) i/ V* l/ T! G2 k8 Q2 \
0 m- |) Y# ?- K% i4 {                        {
, N  k3 d8 Z" s& _- ]; j4 J" C2 B, q/ J$ ^$ {( ]6 Y
                            *pDest++= 0;
: l0 y! ^. ?# O* N0 r5 f; ]& G0 I6 s: L0 h, H: C3 C  I6 @
                            *pDest++= 0;
- ^7 t1 ]! ^4 F$ s) }& I1 S
* Y4 Y4 V8 F" Q& J' v" o                            *pDest++= 0;1 f0 i" H. U9 @  m$ J

4 {/ Y& ]) M5 ]$ N( i; Q                        }
6 J; w  |. E* y8 Z
5 K2 [' z# _  S! m  v2 S                    }
$ _6 [0 ?8 f& B! j, W- g
5 k) R1 R6 z1 D$ l3 @) Z9 ?                    // Always use the greyscale value for alpha / z# t. w. z! N9 O+ `
+ y" T3 x/ u7 I" T5 r5 P* z9 N
                                       
' M5 Y- e9 i; `, }; B. t$ a# U3 o# f$ `* I& A% K0 U
                                //      LogManager::getSingleton().logMessage(StringConverter::toString(*buffer)+"is cool");
# h; f" r3 ~6 ?# n
' J1 `; ]- L* }& m                    *pDest++= *buffer++;! |6 @/ T5 V# [* ?$ |

0 f/ r8 r1 d) G                }
$ ^& `+ K: {+ Q8 R8 _' s5 `+ ~: x
                                - N2 q* o4 `1 U; `3 N

5 |4 Y3 L  e& ^7 ~. Z                        }
6 x9 V: p8 P" N; K
& Z0 a- d: ]; K1 n& f2 b                        // 设置位置 5 Y4 S1 R6 u2 w* g  @' T

) r7 M/ q) K; G( N9 Q% y                        this->setGlyphTexCoords( dwChar,
3 R; @: f6 B8 T
5 I6 C8 l, Q$ p0 k  z                                 (Real)rect.left / 512.0f,  // u1
3 u" ?4 q. T/ @* r- p
: o. r" d/ f) E  \) D                                (Real)rect.top / 512.0f,  // v1
2 r, H$ w7 M: y/ C  X
) e) @" H3 G  s1 m7 d                                (Real)( rect.left + (mTTFMsg->face->glyph->advance.x >> 6) ) / 512.0f, // u2  s; u2 N3 Q; A1 p2 X
+ r: N' D* f( e8 o2 P
                                (Real)( rect.top + rect.bottom ) / 512.0f // v2" t  Z0 H# t3 g0 N

, c+ d2 B5 p$ k( t1 \6 e1 U8 Y, F* {+ h                                        );
+ n) _& w* n% P! ?* r6 O* Q
( F2 b. u4 [# r( d; t                mTTFMsg->dirty=true;//贴图需要更新 9 u, \' S4 j0 o) [- ]% W
5 s* H- U4 d# O& Y/ M) O
                return true;5 a5 E1 f, P8 ]6 P

) D: k% x5 b/ R1 l# Q( o' c( b        }7 Y# Q. f& M9 i! p  m  x) [

5 b3 ?' Z4 A+ B1 R6 N- T  
( c( j4 |) v8 W+ m( I0 I# x& ~4 E0 ^* T
(4) 7 k( X0 Y8 l0 k) K& [5 c: p
9 O( p1 i4 P0 {8 O
        松口气吧,繁重的工作都做完了,就是更新贴图了。 7 y- t) e$ H% o3 N/ L1 l. |6 U6 A

+ `, d/ l4 w, p+ R% r8 G        Font类中~
! g" N* k0 {- c. f. Y& D: z! o) M. U  s& [! s9 I& e
        inline void write()
; H/ N+ Z6 D# j; d4 w" g( ~: Y
, a1 |& ?: m$ }+ F2 d& ~                {* O$ W; \8 R0 z* [4 X+ ]- `
5 ?; Y' O+ h# H" `
                        if(mTTFMsg->dirty)
6 y, ^' g8 Z# u$ P5 H9 V5 b  J5 p& P$ G+ Z6 Y! }9 w/ ]8 c
                        {       % Q5 r+ M) \% R7 j
- `7 M. L  W) C# ?6 V: I
                                // 重新载入贴图,顺便说一句,类似功能的函数还有
& t: t0 M) S7 Y0 T$ I% O  g7 l( z, Q9 p9 l0 C% o
                                //virtual void  blitToTexture (const Image &src, unsigned uStartX, unsigned uStartY)=0 3 J4 N- ?1 m# s7 _# Y. z
; t4 f0 P# z5 p8 U5 l2 R3 K3 Y
                                //和virtual void  blitImage (const Image &src, const Image::Rect imgRect, const Image::Rect texRect)
5 Q/ k" w  }/ M7 T+ P; X& p9 M1 P
                                //不过blitToTexture()在ogre-win32-v0-14-0之前没有实现,没有尝试使用。 blitImage()就算到现在也没有实现。 8 ]" o0 P& Z5 K2 x  n

. m2 c4 [& I+ j/ t% D, z! f  
/ O* h) x" B5 Q+ K9 }- X) N9 [7 i# p1 _: F1 I; C2 W% L  B6 r
                                TextureManager::getSingleton().unload ( mName + "Texture");
( f0 U9 H' E4 J/ ^* F$ d6 l% J$ b( a
                                TextureManager::getSingleton().loadRawData ( mName + "Texture" , mTTFMsg->imgchunk,512, 512,PF_A8R8G8B8, TEX_TYPE_2D, 0  );/ g8 k9 R$ m; ?$ V! V* J' P

0 G, a; y4 A& p' @                                mTTFMsg->dirty=false;
, S7 A* e- U7 L2 p9 I
/ g7 r5 x: c0 k                        }
! c, e& c, U' C4 P' T2 n7 O- A0 |  T$ `0 p
                } 8 m8 m2 C! _4 S8 T2 H' e# K9 ]

' g3 M  U- N8 A2 a# M3 ?! E& ^+ F  
% J4 G+ k7 A- H: J/ @
( k& Y$ Y8 ^, p9 L" q         在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。
( z( S- f6 W% t( z% o
) k$ ]' V' e$ B0 x) F! q- s    j- k# K' [4 ~
, j) T- t, b7 ^  O* i  o
  3 S0 f7 G" n8 C
$ W: X0 x2 t' Q0 ^( ]$ b
4.结果。 ! M1 _9 ?6 Y, w2 {2 k

- W* d# e3 `- J2 N$ b2 c        好长阿,写了好长。虽然多是代码,但写注释也很累啊。重温了这些天的工作结果。就像上一篇一样“在OpenGL和DX9.0中成功的支持了中文,但是DX7.0中竟然出现了运行错误,具体问题还不清楚,还望各位高手指教。”。不过本来OGRE就不怎么支持DX7的,不管了吧。OpenGL中渲染的比DX9.0清晰,是我的显卡的原因么?以上的winXp+vs2003.net+艾尔沙980se通过~。。
$ E, A0 F+ e1 \1 V' Y" i8 J+ ]9 v8 C" ^! Y
        顺便说两句,上次发表了拙作,没想到好多朋友和高人们找到了我。甚至联系到了一个南方的公司,说要做一个引擎支持中文的方面。但是卖完400多的火车票之后竟然因为住房问题作废了,5555,退票少了80元啊。还是自己差阿,如果再多学点可能就能要我了把~。努力吧,争取写《让OGRE支持中文》三部曲。 * x5 f. M/ C7 y

; d5 [* p' s: D: V1 b        下一篇应该是《可以输入中文了》。 3 ?  q+ _8 o, D& ]
5 ?: @1 Q: t0 S- Z/ N# R& E9 ]
        也可能写不出来的~~~~~~~~~~~~~~~~~~~~   
' D4 i" D7 t; j* v. w
( Y# H" u$ o6 g0 p* j  E4 I    相关文件 ; G- z7 _& a' [5 r& ?0 v  [$ P

* \: V6 @/ [5 a8 L    chinese.fontdef//字体信息文件 放在资源文件加中 6 Z% K" M6 C# D. {3 i7 Y3 Y

0 \' p, C5 j. ?    font.png//字体图片 放在资源文件加中
* i( L* F. r+ B% ]/ J& H$ @7 b! E0 n7 [& x7 r. B6 D' s
  
1 [: O1 I2 k/ s' R8 [$ `, `) [" Y' M& q( S, A% `! w/ A3 a
    OgreFont.cpp! [2 S0 B( F: o7 z6 \& f' a/ Y- _

8 g8 S" q1 C; S% h# x    OgreFont.h
# D' S8 `6 a6 a" }; m' m  f
6 K3 [0 u# ?! ]& w( `2 N: C6 I7 l    OgreFontManager.cpp9 Y0 O# \. L  b& G/ e) Z' e6 v

6 ]0 o* |1 f5 B  T% }6 t$ c    OgreTextAreaGuiElement.cpp- \8 I# d6 H  `
% s. Q* a* V! \' x3 M* ~2 R: i
    //上面文件覆盖同名文件 就可以 先备份 / U* j' V! j8 N' Z) ?0 |

, b$ n/ d9 g  v* \1 n6 j$ k9 H   
' ^1 C% p. K* p( u  K3 y$ t
8 [2 _8 ]/ G& w8 @: I. g6 b8 }: B   solo5.ttf//这个是一个中文ttf 我直接替换了原来的ttf. Y* f( Z; b9 w; [$ u5 v% E
1 v% p* Z( h+ Q4 q' f; Z
   unicodemap.h//这个重要,是换算unicode码的数组(文中提到) ) H  o, z9 Z& p0 U

& F% f  O- I9 b2 ]  
9 |" W2 ^3 T8 [! Z) y2 j
/ N8 o4 I8 a$ G2 v, Y这个是在ogre-win32-v0-14-0基础上改的(上次是ogre-win32-v0-13-1), 8 x8 v& W4 `: q

3 A( c& ~/ k2 T0 W6 [; h请到http://sourceforge.net/projects/ogre/下载 - I: Y8 E- y7 k" p

" d8 j/ c# g, a  J( V5 S5 Z配套档案下载:http://www.gameres.com/Articles/ ... /ttf.files/file.rar
$ T( s; I% n& B, ^5 [
* ]" ~& |7 i8 N- D6 Y- E  A4 J6 a 免费打工仔QQ:1850070
7 O5 o' h" ~( N9 U, c& X
( A0 ^. O; E9 x9 y( zFrom: GameRes % t: s: Q. ]. j/ G9 k8 X  T9 K6 U

( N1 ]1 u6 ?, P6 r' Y9 [& hhttp://www.gameres.com
7 X. N6 C/ c! s+ [4 g0 F+ M2 t" q0 j5 G! ~. [, p, I
上面图中“免费打工仔TTF:213.786”是TTF 其他是位图的,中文的位图字体也小修改了一下,支持半角字体了~

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

冒险解谜游戏中文网 ChinaAVG

官方微博官方微信号小黑屋 微信玩家群  

(C) ChinaAVG 2004 - 2019 All Right Reserved. Powered by Discuz! X3.2
辽ICP备11008827号 | 桂公网安备 45010702000051号

冒险,与你同在。 冒险解谜游戏中文网ChinaAVG诞生于2004年9月9日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

快速回复 返回顶部 返回列表