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

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

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

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

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

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

开源的图形渲染引擎OGRE(3) --让OGRE支持中文TTF字体  n$ f9 Q# @! S% k
( x  d- x' S7 H
0.还是前言
' g; n0 c9 e  N1 K5 w8 r$ U
7 d% T4 W* C/ x- Z: l" }        如果你希望能看懂这篇文章,请先确定你已经看到了《让OGRE支持中文》(http://www.gameres.com/Articles/Program/Visual/3D/OgreSupChn.htm),因为本文是在上一篇文章的基础上写的,并且假设文件都已经按照上一篇文章进行了手术。但是如果你只想简单的使用TTF字体,只要下载本文附带的文件,重新编译就可以了。
+ I$ M/ J9 T* L! x1 L4 }* T. u% Y& h! v1 P3 @
1.检讨 : i& U; j2 w) \0 I
! |4 x/ `6 f5 _/ u& D
        正如上回说的,我们已经实现了一个位图的字体。但是当冷静下来思考时,就能发现这种方法的诸多缺陷。读入一个2048*2048的位图,等于在显存中保存一个2048*2048的贴图,不说是否所有显卡都支持这么大的贴图,单是每个Font字体类吃显存的胃口,就足以令人心惊肉跳。如果定义足够多的字体类,我想你的游戏的配置要求,在某些方面足以超过《DOOM3》了。
, M2 p! G3 n, l! E% B  @( l0 P  P  i$ x
        而且这并不是唯一的缺陷,文字大小相对于位图大小比例相差太大,导致浮点数的文字位置误差很大,你可以在一个文字旁边看到其他文字的影子。(虽然可以通过增加文字间距来解决。)还有点阵字体本身的缺陷,就是字形单一,不适合放大缩小,一些文字边缘的马赛克,足以熄灭任何玩家的投入感。
: t1 d  _% w! m0 r% ^5 t9 s* K% I- ?3 M& S+ ~6 `) e
        似乎TTF是唯一的解决之道。 : i- U9 Z) N% [/ T
" H& _* t& h3 h
2.基本知识
: v9 `9 |4 w$ p  z& C0 H( h. y" g, Z+ o6 y$ _
(1)TTF字体。
) Q+ G% m5 l5 r& Z9 m
8 q" j* V; F  I. j# f7 c        TTF是一种矢量字库。我们经常可以听到矢量这个词,像是FLASH中的矢量图形,在100*100分辨率下制作的flash,就算它放大为全屏,显示出的画面也不会出现马赛克。所谓矢量,其实说白了就是用点和线来描述图形,这样,在图形需要放大的时候,只要把所有这个图形的点和线放大相应的倍数就可以了。而且,在网站上有很多的TTF字库可以下载,或者你可以去买一些专门的字库光盘。然后在你发行你精心制作的游戏时,可以顺便捎上这些后缀为.ttf的文件就行了。包括Quake这样的惊世之作,也都是用的TTF字库。
8 D9 v3 N/ }, d# e1 i
( B- {1 [+ o/ D(2)FreeType2库 5 ]- C- l& E9 O  {5 z4 c) R

6 I/ a" W$ L: R% k" x0 t        在http://www.freetype.org,有一个FreeType的免费库,而且是OpenSource的。它目前有2个版本:1.0和2.0。其区别在于,1.0只能读取TTF格式的,而2.0支持更多的文件格式,在使用它之前请详细阅读所要遵循的Licence,以下是摘自FreeType2.0对字库的支持列表: 9 a+ Y$ X0 G% q
1 ^* D, a* P% s+ Q% t  y
        TrueType fonts (and collections)
  P4 w4 g, g9 E$ n
  w3 |' z8 o3 o9 U4 V9 B. ^        Type 1 fonts
: E7 w9 b$ d- m1 |7 |# e
7 ?* `/ l8 X  C$ {$ t! D& L" `5 V/ U1 X        CID-keyed Type 1 fonts
0 M4 z6 j2 {" e% j4 d
2 j$ S2 G' M# i, n# k        CFF fonts
0 ~) n/ b% Z: S4 T9 G: P( o; l6 n9 {6 h3 I( ]* k
        OpenType fonts (both TrueType and CFF variants) 4 W* i! V4 v# h  L
! \8 A& Y- |: H
        SFNT-based bitmap fonts
$ Q9 c9 M$ {& m8 R/ x* T4 Z
! v, d. t3 S2 G+ _        X11 PCF fonts $ `( L) j# N, d* r" ?6 X

8 T$ q4 f% j9 ?( D, a4 g5 f1 _        Windows FNT fonts 4 D+ e# J5 D# w& w$ X; H, C3 v
# k% c* E* M+ \
(3)“主体思想” " ?/ i6 E, _. t  g1 |% R* y

7 P- X1 c! X& F( I+ c" y& F( L        请参照炎龙工作室的《游戏中汉字显示的实现与技巧》这篇文章,可惜使用的是Windows API,作者千里马肝,上网上搜一下吧。
/ z* K* |$ e( t  A7 T7 Z* B2 i0 |9 B4 M( T; X4 j
        附带说一句,上面两条都是直接从这文章中剪切下来的,>_<  不要骂我啊,不知道算不算侵权呢。
4 }8 f- |! `* s, r' v* i* V  X+ u, U& k
3.动手术---比你想象的要麻烦 " O8 n/ O( f  |% |5 Z
(1)
% y# y2 H& \+ L" O% S" U+ z        首先要告诉字体类,我们下一次渲染需要哪些字。以便字体类可以在需要的时候释放不使用的字体。
5 l: R% y" Z3 f) \3 j8 k( k) w9 X' L7 w4 c& E
        在Font类中~ ! w! X4 G. k. L: V* U

' \) G0 T8 t! w( L6 p0 Y        a.增加数据 bool mUsing[OGRE_NUM_GLYPHS]; 用来标记文字是否使用。 2 v' t, z/ G# d4 z* h
% v$ z9 D$ U! E" ^
        b.增加函数
1 H  H7 P# w1 o, N& c. c) d. g
                inline void setUsing(std::vector<unsigned long>& caption)
& F! r; c5 I5 n: f' b$ d4 @+ ]: r' R/ |: s8 z8 z0 P
                {
% H5 e  N' _0 a# d! s) q- o: v. n/ T, J5 i6 b  ^) z; e$ f  m
                        memset(this->mUsing,0,sizeof(this->mUsing));
2 }8 Q6 q0 S" v5 h. A
5 y$ L1 _7 R9 T- p: T. S4 U5 B% b                        std::vector<unsigned long>::iterator it;4 k1 ~( q/ C6 U' ^& \

  R0 k, n: r1 H) |                        for(it=caption.begin();it!=caption.end();++it)
- Y7 E, J$ z+ j- ?; h
. I2 d/ {# H4 g5 c% _! B                        {
( N! g/ W3 N9 J7 c7 M3 d- n3 a9 V& {6 w1 H) \
                                if(OGRE_GLYPH_INDEX(*it)<OGRE_NUM_GLYPHS)9 y; t6 y4 Y% s6 ]' k7 g5 }8 H
( ?; u2 P( I6 x2 B$ [9 ^" ^% ?! W
                                this->mUsing[OGRE_GLYPH_INDEX(*it)]=1;//标记文字为使用
, k& U( J4 X; q
8 J7 G( C5 {6 s1 x! R                        }
7 c: f. q8 J5 k% W" |; Z$ [) b5 ?" t9 U# C
                }
9 w. d# D" k9 B
, V5 N4 \9 t: r1 w* ~        并在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。 & p- |  _/ \  L. D+ d: x. L
(2)
5 U1 ~$ V2 n; k* M1 T/ k
  Y) P7 [! N. k8 e4 K3 Y/ M        然后是修改void Font::createTextureFromFont(void);, n- ~( Z+ K9 b4 V/ t0 A

; X) [& P- ^! n        Font类是通过void Font::createTextureFromFont(void)来把通过FreeType2分析好的英文字画在一个2^n*2^n的贴图上,然后再保存英文字的位置。 1 g. }8 D  L' P  s3 m5 P+ U
" n( z6 S* j5 ]- s0 f! F3 r/ _5 G5 n
        我们需要修改的是:
6 U$ Y4 y6 y1 r5 @/ F/ ]$ v! s
' @0 [5 `2 D3 u% x        a.从函数中分离并保存画字的FreeType2和辅助变量。我们通过一个类来保存和处理这些变量。
, B* u5 U8 n- K" X, o0 d; X9 T/ l! K: \# g0 J( {# v
        class TTFMsg/ b3 j# R$ j9 I2 n& b

" I0 K* W: n: [  E1 k! j) G4 I2 O                {
9 T$ v, D5 g8 R9 p' h/ v7 \) k
                        class Max//类中类,用来保存几个"最大",7 M) l, |! I8 v8 ?4 H- U
/ q$ X; {6 q. K2 _3 Z" i
                        {: ?: X- ^5 V( }
2 Z! j2 b* `& s! P; M
                                int nothing;//这个是用来占位的,没意义,反正没他就运行出错,可能和数据对齐有关吧。
' Y4 \! G& o2 J( n& r% I
, h' {, G5 d0 Q: l5 @3 ^' z                        public:5 ?4 B. F! f$ N& ^8 C
                                int height;//文字最大高度 & }7 @% A! x8 b: n+ [; G
                                int width;//最大宽度
0 g7 S% l  r* M$ Q' o' ]& r3 j$ H                                int bear;//最大空隙? . N( H- G) v' _  x+ {. J
                        };
$ q. \$ L$ z: M  }. Y+ r: D                public:# n; U5 }4 h0 Q! k
                        FT_Library ftLibrary;//FreeType2用
# T$ @2 w+ u' o6 }$ ]. h                        FT_Face face;//FreeType2接口?
2 p9 Z6 v" j1 W3 |4 M0 D% q                        uint char_spacer;//文字空隙 ; p4 X& A: a4 c0 X- w+ I" j
                        SDDataChunk ttfchunk;//数据块,用来保存ttf信息 9 x  H* `* O/ O
                        FT_F26Dot6 ftSize;//FreeType2字体大小 * b- S4 d% f, q. L* ~3 q) _+ ~
                        std::pair<uint,uint> point;//在位图上画字的点 . w5 i  a- Z- }& t1 n' f
                        SDDataChunk imgchunk;//数据块,用来保存位图信息 * M- N; r  {4 x& ?( D
                        bool dirty;//标记,看是否需要更新贴图 7 i1 ]7 S5 e' X  _: i! ~( d. R
                        Max max;//几个最大 9 |1 L0 B; s; ~( M) s

: q; A; D2 }2 V% v) Q                        inline bool init(Font*  font) //这个是初始化函数在void Font::createTextureFromFont(void);中调用.* y/ r8 p! {; P* d
; T+ h( i2 N: m& ]/ c) _2 G& ~
                        {      
5 v+ E* L6 S2 G# e
9 E& L, L7 t! Q1 V& W                                //以下都是初始化,大部分都是从void Font::createTextureFromFont(void);移植过来的
" W+ \$ i4 s5 g* {
5 q5 c7 x' _. U5 j: J; a: T                                dirty=false;$ S) Y- z# C2 V6 v4 Y! j
( \0 Q/ H& M8 ~* D( E+ W
                                if( FT_Init_FreeType( &ftLibrary ) )3 g% o7 j% A& c6 X+ Q! l5 m
, g& |1 z3 D4 @9 _
                                  Except( Exception::ERR_INTERNAL_ERROR, "Could not init FreeType library!",$ y( T" d* F/ s
& y! o! O( t" ^1 k% t$ v
                                "Font::Font");
2 `4 |' m! m4 ~' S2 ^
1 H9 b2 z5 D2 w+ Z& m- D$ C                * @( ]9 }/ i1 H3 T1 Z+ w

" B, g# z; e  I& X                                char_spacer= 5;
/ p* a# I: ~$ A+ W( s2 w
: h& ^/ z1 t8 G; K9 p9 ^                                FontManager::getSingleton()._findResourceData(font->mSource,ttfchunk);
1 `2 k- p  w) V5 n3 T& p! c2 B# v# u: A  d( d4 k6 F" S5 p
                                if( FT_New_Memory_Face( ftLibrary, ttfchunk.getPtr(), (FT_Long)ttfchunk.getSize() , 0, &face ) )
5 C# i0 y* f  J7 L; `
& G* [& T4 z" `+ v                                         Except( Exception::ERR_INTERNAL_ERROR,
5 U' C0 `; q2 ]  g6 `* O4 V" Z  l6 N: ?0 u! ?% `5 J  X
                                        "Could not open font face!", "Font::createTextureFromFont" );( t( v+ ^5 ?- p

4 R  o! z+ J) F                                ftSize = (FT_F26Dot6)(font->mTtfSize * (1 << 6));
) P' N3 u; ?# h% |$ N( M
: {6 @5 l$ R& Y7 X* p8 Q  F                                if( FT_Set_Char_Size( face, ftSize, 0, font->mTtfResolution, 0 ) )* X5 t4 C! n( v, G

; X  r9 ?) N( B4 d1 C6 H5 X                                        Except( Exception::ERR_INTERNAL_ERROR,
( p( s* l0 W& G2 V
8 s( \; p: ?: [7 D" V0 o7 L                                        "Could not set char size!", "Font::createTextureFromFont" );3 |* j1 ?# D/ I8 |; E  }
5 A; Y! h% |# M% s& b7 [' M
  $ ?' P5 s5 ~3 k

( t6 D. ~4 n- V# E4 F" u  I5 V                                return true;
7 m: Z5 m- U* S% M9 `1 x& G+ v
4 V6 Q2 `( R9 b: c8 T                        }
) N& n0 s/ l0 _! N" A% b3 i) W) `  p5 n  }1 ]) d
                        inline bool done(), q1 B4 F& B" f, F/ \; |

& _# z7 E( k3 m7 ?3 p, H                        {
8 ^. V) L0 A1 J* i3 k7 I: R
9 A7 W! P0 p7 h, @, ^7 G- b                                //在Font的解构函数中调用的,本来应该调用下面两个函数,但是不知道为什么一调用就出错,不用倒没事。 7 S! s  c( D5 ]- z9 Z7 A

1 O: X9 q: Q% h# W" b* O6 N                                //FT_Done_Face(face);
. J8 d, O& d' I$ v! u8 N! _5 {5 o5 W/ {% m8 c$ b
                                //FT_Done_FreeType(ftLibrary);( z  K2 m, l; G( ~, _/ ?3 N9 f* L- C
+ y- X/ Q' Z, O- D) C
                                return true;" |% B2 P0 L) F$ W" ~

2 Q0 H' p* F; Z                        }
- n( S/ n* I0 E/ u+ y0 U! P5 p+ Y+ Z+ P: n: e- K7 A
                        inline bool getRect(Image::Rect & rect)//这个函数以后用的,是用来找到可以画字的贴图的空的位置
; A  T& J( Y6 @: u' `8 U+ X
( g1 X8 v' U: n& f/ q                        {; ^2 c% }3 p  T/ ^) M( t7 q

& G5 ]& Y$ M# u                                if(511<point.second+max.height+char_spacer)
9 {+ G8 q. I/ c6 k3 P$ Z& U% i6 x/ J) r! j* S9 T9 _& T
                                {9 \! T  \% z4 W# o" T

$ {2 A2 V) D7 A9 b/ }& w  M                                        rect.right=rect.top=rect.left=rect.bottom=-1;
! u" l9 t: B3 z3 s) x1 L) g* n* E3 z2 N$ @0 B6 C" N# l  u7 ^, X
                                        return false;4 z+ B/ c2 k- T: ]$ `$ d

& i. g' n/ ~$ x- L3 C/ Z                                }; A  s, {1 Q6 R$ G' A( a

3 ?4 j/ d7 m! _. D( f                                if(511<point.first+max.width+char_spacer)
' @: p+ j/ ?6 b% c$ ^# h, ]; s4 A4 ?4 b: Y" ]$ {# h4 f
                                {. j8 Z" r) C+ O% Q8 G0 I

! {" t3 O2 e" T" H, R( }                                        % o4 {2 m8 K; m+ j4 k

' A* G! K) ]0 K9 A                                        point.second+=max.width+char_spacer;
2 o2 F* y# W& E: L6 i: C
% n' G2 I8 f# Z, Z                                        point.first=0;7 S1 ~+ d3 ?! H) G0 y% V/ Q% q
7 ^: \6 J6 i' `" C1 d
                                        if(511<point.second+max.height+char_spacer)# r6 c; M" T2 S* f. G

/ T- n! F/ A& O                                        {
0 g$ T5 ]' l' W; n5 ?5 k8 x- z6 f* m5 c
                                       
) N  Q4 y, r# l+ f! g1 A$ w' g2 d4 a8 l# I! C( b7 U
                                                rect.right=rect.top=rect.left=rect.bottom=-1;
  t+ T! W- I, R4 s5 K3 a/ }+ h5 C! k7 d! M, a; y
                                                return false;0 Y. l$ Z) V7 U, T
% k9 `2 l7 |5 f3 R9 H
                                        }
$ Q1 d7 ~+ ~1 h6 F) Q6 Y3 ]; V6 {
                                }' F7 J' N3 {+ E! Z9 c- O

/ n7 ?0 m6 q$ U                                rect.left=point.first;
- I  U7 P1 r1 w* C/ |
9 k/ F! t: F5 _" ?5 p. r                                rect.top=point.second;
) G2 F4 Q7 v# P- C7 M. z/ `: d# t* ?2 Z
                                rect.bottom=max.height;; f6 u5 Q( @# Y+ a$ f$ R
1 g5 `  e! X+ o) Q% r6 A) F2 {, S
                                rect.right=max.width;
% X- j5 Z7 f+ F! y7 u1 e! g9 r$ _* T! ?2 m
                                point.first+=max.width+char_spacer;
" Q" S" W% b3 r* U" Q6 L) j: c/ C- c
5 j0 A; g! C1 `4 E                                return true;
9 G$ |- q: K* B& L9 E" i% u' O  W$ T9 E+ D( g
                        }8 f0 q. M. Q( h9 v

$ G; P. P+ F" n3 ?& S) p- q                };# Z! ^4 a. X: n; N# w( d" U: ]0 U
  n9 i! z& E3 a( G! A4 Z% G
        上面的类定义在Font类中,在Font中增加 TTFMsg * mTTFMsg 数据,并在构造函数中 mTTFMsg=new TTFMsg;
8 T: J  F- \9 s! z, P
7 i9 g( P* {  t, C  b        0 Z# k- C$ S3 f' P# G
; D% X9 K# T+ p% M8 l( R7 L
        正是修改void Font::createTextureFromFont(void);函数,主要几点,首先是分离出很多变量和构造到TTFMsg类中了,然后是贴图从2^n*2^n变成固定的512*512,为什么要这个数字呢,因为256太小(废话了)。能保证512*512大小的文本区不会出现不够画字的情况(所有英文+符号+没有重复的汉字),这个安全区域基本上是够用的。(什么,你要画满屏幕的汉字?哪你自己看着改吧。)还有一个重要功能是,要找100个汉字,找出最高和最宽和最大空隙作参考。修改完成这个样子了~  i3 Q1 W1 i! \; q

7 J: _* u# N! T/ b    void Font::createTextureFromFont(void)8 h, |+ m! l3 `2 E( d
; Z; t8 Q9 {, M* R& h
    {
6 G, W& ^0 q. h& s* k6 K& O( u1 F7 \3 k5 E
        mTTFMsg->init(this);//初始化FreeType2
8 f1 F$ E& g* r4 b8 P' w+ N
5 ?( A6 I' A- B3 D6 }9 y7 E. [% P& W        uint i, l, m, n;
5 J. C" M* U# j. Q9 c  H8 Z% K: |
+ Z5 y. |9 Q, D, O; F        int j, k;
( ]2 v6 p- y. G4 x- s7 |  e  |& s) u( t7 I6 H6 P/ W
    R$ S$ Z5 k3 U0 u& A

# k0 j/ U6 o8 Y& [" a# E6 z( r0 h9 L      
9 g, z7 o1 I( r) u* _# I% p7 v1 Y# D4 p. y7 W" b8 b
        FILE *fo_def = stdout;//啥意思?我看不明白 8 O  f( g2 ~5 [, o8 G

- W, R0 F( s: N0 N/ h  
$ |# x( ~; L' Y' P# R! x! P* W& |+ ^+ J/ Y7 T* F
        int max_height = 0, max_width = 0, max_bear = 0;
7 m: {6 P2 R' }5 n7 k' a0 w- Q/ q, M
  
# Y3 ]( a6 A/ o; i1 s$ A
5 ?; ]. x9 r8 a$ b6 c7 ^        uint startGlyph = 33;% m/ M6 c. ~7 H( X
0 h4 ]4 M8 \$ {$ O9 d
        uint endGlyph = 167;9 A! e* ?6 v& l2 h; @! n

# l: u  Y9 F- w0 Z; ~8 A" U  
7 v+ m8 _( O, z$ h! B8 p+ c
! x/ ^3 w: l2 n1 m9 v1 \! Y        // 找英文的找出最高和最宽和最大空隙 # w1 e& D1 ?) S2 {9 J3 Y6 d# ]
1 c% n6 \$ u) d4 c" y# D6 v
        // Calculate maximum width, height and bearing
5 Y4 g' F+ J! ~3 B; i5 t' z! c8 Y3 }; l" u3 Y+ ]
        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )
, }2 @9 S/ G% c3 S! f  B* D( o* j. m& n+ y; }6 P5 ^
        {
' B  y+ W, a4 x( n% ^( S6 @
9 c" V+ N, g, Q: a8 e            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );9 _5 G5 X7 H4 a, h

1 L  k1 X1 z% A: W$ t9 E2 B; h" |  `            //以后的 <<6和>>6都是FreeType2中的数据和我们使用的数据的转换 ; j: ^$ [4 C9 O2 l. G/ z/ K. _% i; }
& s6 K" m( M% H1 L/ {& T
            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )
% `6 h' [0 x, O: j' y" p0 V! i
& s/ N1 w& P% v* l9 b                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );
8 Y" w' L' M7 Q
& d( N0 W7 o  J- t" L4 `            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )2 A6 m. \' v- |0 O$ @1 K$ U, o

" s4 N9 Q9 r, [                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;7 a: t) l- d9 l$ L

8 @+ r4 C6 t8 `5 @  n! N  ) }9 E/ B1 x. M& m' |) `
! K; l! o. U* ]' X; k: u" Z
            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)
4 G% s. X6 I# e- g8 ]7 F0 h9 v9 D. q7 a
                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
" B) H2 s5 w* C1 Z9 P0 }
9 n$ L5 N! U, T        }5 U% {/ M  H8 f& F9 j4 v( i
- n, r1 ~8 P* O0 Q- x) G% a
  
4 d- E' a$ _  q: u7 @, H# K1 \  [5 u# `/ U3 Z) [: m% J7 T
  
) Q; Y6 X+ [+ W, J+ u# ^% d
& _) r% Q  ]9 \; z" t, C        //下面的for是找100个汉字,找出最高和最宽和最大空隙作参考。姑且认为最的汉字就在这一百个里了。 8 T. ~6 g( N+ b' [6 n1 n3 t
0 P$ P# A5 P; J7 N
        for( i = 20643, l = 0, m = 0, n = 0; i < 20743; i++ )
3 h8 L/ W" v+ F4 {. b- m" f
% u- P' Z& j, e, Z        {  o4 S5 f; x- y" J) u6 N9 }5 I

5 F; u9 V3 V  D5 H6 z: Y1 ?            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );
5 l+ {, K8 e" M/ z, J
' J1 Q3 R1 p4 I. E  
: k" h+ D8 w+ V; P, @# c0 S  E  P5 k2 K! ]" m/ `( ?: y& f+ y
            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )
7 Y- t( h1 {# `" M+ y$ ~5 J0 v) W+ O2 r
                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );7 P4 y8 b4 X! l$ b; b
+ |& I, ?$ t+ R4 T5 H+ o
            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )
3 Z; `6 `# J. a$ R: [
0 S& G/ a  D- `0 r5 C                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;6 q$ f5 n6 @9 z: m
$ d/ P. M/ A3 g
  
& g  T2 d1 ]) Y% L
7 d  H' S: F, h: p6 j+ j            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)
1 ~  a+ f8 e! A' e
( L0 |" j+ m, i( ?1 Y/ j  k                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
3 V3 o5 y* @7 v7 g! w2 f* \8 S, g0 D: w* ]0 f$ ^5 F# N
  4 q' V" Z; T3 R  C% `4 M+ e& [

  G* X+ V8 h  Y4 Q, n, W                        
: j. Z' l9 ^% i0 D8 a1 r) j& \  K+ t' z- P2 C6 ]* ^! C3 D& [0 Y
            if( (mTTFMsg->face->glyph->advance.x ) + ( mTTFMsg->face->glyph->metrics.horiBearingX ) > mTTFMsg->max.width)3 G, A  u! t- t9 V1 J& m# {7 U7 {

  d; H  `1 S: Q8 f( n                mTTFMsg->max.width = (mTTFMsg->face->glyph->advance.x  ) + ( mTTFMsg->face->glyph->metrics.horiBearingX );
8 f7 E# e$ s2 U1 y$ r* }
1 g1 U8 C8 O+ d0 J! l0 r$ g        }8 E7 H5 l! g! ?! {# x+ e! L" M" p3 v
! x1 b: ^' |& z
  
3 m9 f; c# z7 O" ?# c4 q* g  |0 H4 s$ O, z& u& O
                //下面几行行不需要了 我们要512*512' |! v: u0 N' N4 X* x- W* n' m

8 K5 T+ @% H5 _  H+ ~+ `                size_t tex_side=512;//就是这个了 512, \8 f) @7 N5 e- Q1 T+ G9 k
# g5 Z1 P, k8 c% k2 ]6 b; b$ a
        //定义数据宽度 因为是32位的位图 四个char为一个像素,为什么要位这么大呢,难道不能用8位的么,我尝试着改来着,不过改了之后就不透明了。望高手看看能不能改。 & s. o! y. b! h/ b* J
; q3 k8 v2 ~4 h$ }
                size_t data_width = tex_side * 4;7 L( w4 M! E* V/ F1 j& h4 T, }( h; h: G
  V$ ~9 R: b+ H" D4 ?' F" i1 T/ l
  : o- G1 I. g+ A7 P: @: h

0 `& r  F2 h+ n5 A4 V, i# l- o" K                LogManager::getSingleton().logMessage("Font " + mName + "using texture size " +5 N* L1 V7 L6 f1 T

- m$ p/ ]. m- f8 H: N4 R                        StringConverter::toString(tex_side) + "x" + StringConverter::toString(tex_side)); / Y+ ]% U( V0 t
" Y" D# q$ @0 o9 s9 g2 b  S3 z
  $ m" U9 m9 t; K/ |
6 a7 m: X& e( G* c9 M
        uchar* imageData = new uchar[tex_side * tex_side * 4];//设置一个空间用来保存位图 " o, Y2 H/ S; x- f

6 B7 H: Q+ x  E7 {" g                // Reset content
# C5 k. [0 r/ x% y8 V+ P; Z5 U4 ]' c' Y1 u* P6 \9 _
                memset(imageData, 0, tex_side * tex_side * 4);//清零
4 e3 j9 s, I1 B" l( K# y- L; U
  t9 B1 U3 ?3 b! G0 @  
' M3 b* \6 h, _3 l6 o. j- o
5 ?: ?9 A% g  @8 l5 d. Y        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )//遍历每个字,
8 F& S. w4 M) {7 A' m' O0 Y) F" L* E: B% @* l7 `( W
        {# t. f$ b. H+ U' t
& S4 R/ h" E3 m# ~
                        1 f; n$ S% \; E/ L4 g% b) P- T3 g
" q: Z- P/ z- q, V9 K5 O
            FT_Error ftResult;
" x$ e7 W9 x, f4 A' u3 @5 b; C  r
+ ]% Q0 D: R4 |% C( z: y1 f  2 ~: \% f$ N2 m: I+ [7 e3 F

5 [% W4 r  p& W. |. C% d5 j            // Load & render glyph
7 g! }# m  c1 W9 {/ v
7 R# a# k5 }5 q; t6 f7 u6 |8 j            ftResult = FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );//读取字体
+ R, Z1 F+ [$ l
2 S! h5 v. P5 f9 }' b            if (ftResult)
. s& \7 V7 c+ L3 t! h
) j5 u4 K8 [4 C+ i            {8 t6 W& x1 W/ y  C# F! l- S
) H' z' f8 O1 G( s1 |; P4 R
                // problem loading this glyph, continue % Q3 \4 @4 j! a* n( ^! z) n* x

' ]0 H' @! `4 Y                LogManager::getSingleton().logMessage("Info: cannot load character " +7 [/ r4 T+ d( I

6 F  t! a6 x# X3 N% @7 T/ |7 u                    StringConverter::toString(i) + " in font " + mName);
1 c8 k* A8 x3 o, Y9 H. _. |
' M9 j# ?  |+ [, n! m                continue;//如果错误跳过   q4 u/ Y% N3 j# e
! u/ ^0 T9 T7 F/ K
            }
% q* ~' P3 a& t) x7 h4 _9 E$ r" D8 x" L  q( _( J( U% t0 W! a
  
6 U( M& R7 J4 B5 L: K8 f; e- |1 o8 Z! g
                        // 应该是字宽
. @; v) i- O0 o" Q' |
9 j% g0 c; D) K$ X! a                        FT_Int advance = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
/ ~9 t# B1 _$ Q- q" M7 Z3 p$ M: S( z% Z9 Y- b
                        $ _3 a1 h8 D% F4 d- N9 {, Y! N
$ k6 E' k2 ?  ~" E( i
                        // 得到FreeType2的位图
8 y4 M  t9 H# ^1 E
, e  W# m- ~7 B% U            unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;2 u8 h7 R: T, k* l4 K- U
* f7 M% f) ^! S: o
  
/ X/ h" S1 J* z+ {) D. F1 e) I5 I& ~! h# B& V
            if (!buffer)( c) Q9 d4 r$ ~, u- u4 l
1 y$ }% K! }: ^5 J& C% _
            {
$ O6 ]2 @! S" t% ?) @3 K1 y  n
" x, ]5 w& H. V9 @9 \- z4 X6 o                // Yuck, FT didn't detect this but generated a null pointer!
7 N9 E; i; |$ v: C9 `
3 a! M6 Y; P& I7 E) V- ?# L                LogManager::getSingleton().logMessage("Info: Freetype returned null for character " +
9 X% b; A  \& [- W
( U3 `, G' S( @" Z                    StringConverter::toString(i) + " in font " + mName);( M2 a' r- e( i& g9 y

8 M2 A- y. W  I9 O: L# V. W. o; {                continue;//如果得不到跳过   E% j: \6 p' h! k$ a

( B/ y6 W) M/ Z: l            }
* E! ^' T/ J2 D1 l& I
3 S; H, w+ g. F0 R( p+ Z  ( d1 X3 X$ m( I9 w& @1 U
, u; g* P  d+ {5 n8 \: E
                        // 得到y的空隙 (最大空-空-本字空)就是说空出这些字底部就平了
1 ?, q! I( R( e5 N: W0 `5 {$ j6 p8 Z
            int y_bearnig = ( max_bear >> 6 ) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );
$ ^1 Q6 i9 S7 Y  |' S# U& a5 U6 G; h/ f; k
                        
3 A+ X# c3 Z# w3 ^: z3 y
8 i4 _$ r- N  D5 M            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )
* c1 H! b- P5 n" ~; C& O* P& c8 b% `
            {5 f) W9 D( c/ B+ m. b' x$ V4 {

3 k2 N" a2 k$ e# b2 C                                int row = j + m + y_bearnig;//相对行+本字在位图的总行+空隙
1 S% _1 E; U- s* e2 t3 y
- g5 K5 u9 U  X& s                int col = l;//列 * s; O* J4 j$ Q7 s' p) w- [* \2 i

: A. J! @- m- ^                uchar* pDest = &imageData[(row * data_width) + l * 4];//找起点   
6 `! N& G$ ?# r( j& Q, h1 h' ^0 |; P  m6 v$ I
                for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//画图 ! q2 k% Y. w2 w6 u/ Y5 a3 u
2 H" w7 ?- W( _5 S
                {
+ r; N* y; V* Q% _, n, F+ w1 _3 }0 Z
                    if (mAntialiasColour)//看不大懂,难道是灰色字体?   G+ T- H: q; ]& |
* E' ?" @& \1 F: I+ J* Q  X' P' R
                    {
" n$ e% w% n9 X4 R: z4 q; d/ }* E
2 L8 f, q7 q. v2 U                        // Use the same greyscale pixel for all components RGBA
% s. A/ p& n/ n; F8 f+ `; a
; @5 I) Q, ~" g/ B  O0 U' w/ O                        *pDest++= *buffer;
( G" T+ k2 [/ v4 s* Q/ O' f  H. E) D7 }2 L% C& H0 X! p
                            *pDest++= *buffer;2 U4 Q; p  ?. n2 \4 H  n% r

+ d9 M- ?  k$ Q$ w& O( T' s9 l2 R                            *pDest++= *buffer;2 V6 K! x& z' m1 Z( K  U
8 M% j7 S6 W  O. C9 M
                    }0 g# d6 @) v# T$ v+ l$ M5 _7 u( {
* t- z6 L6 J! E" P6 b
                    else 7 p! r, ?$ C2 T3 S1 p
, f' i; O0 B8 v' t2 j
                    {
) u( U2 G, r% b$ G& o' e* |8 w3 O5 E8 l
                        // Clamp colour to full white or off
  E4 ~6 B+ I9 W. I
/ }# h/ b" \8 S                        if (*buffer > 0)" d/ y: ]5 K; O' v9 X7 g3 ^

* R+ A  p  ~1 {                        {
  l& F. _+ d! p' U  A( ~, ~$ ?% b8 I# q# o8 m6 ?6 i
                            *pDest++= 0xFF;
6 [# G# n. Z. ~8 i4 z. _0 k
7 I0 E) P- p- `" g  u, L5 y1 d' [% T                            *pDest++= 0xFF;' M$ h" ]2 n. ~
2 z( w$ F' ?/ X3 L' Y- a7 a. R" w2 F
                            *pDest++= 0xFF;& a, A4 o& k& b4 ~7 E" L. t' \
* [- U6 K$ d4 L. g8 R  V
                        }
" H8 s6 a3 ]8 w9 X7 N- S' n9 d2 D3 S; ?- ~, k" w
                        else 1 o7 c! f- b. c0 Y% X( h
- h% f1 O8 @5 k5 ]; H7 H+ l/ U. y7 b
                        {% b( Z: \0 |) I: H6 R
' `+ u+ E. |( y- ]% h4 y4 r
                            *pDest++= 0;
) L3 w- R1 K0 R# h
8 Q* F4 `% F8 H/ N0 }3 p" \. Y                            *pDest++= 0;0 t0 X' A+ u) I3 o" \; G4 L' A" n
6 M% M6 P' [; S8 i
                            *pDest++= 0;
/ D) T, h% z+ N0 m$ e: H" y- p- M" J7 L( D5 i" p* g6 e) J, ]8 x
                        }
4 b( H/ N0 L: A# c5 l
0 c9 [- W# B& |' g/ M                    }' c4 m: P; @% U# |. L. Y
# X$ P6 T6 g+ Y3 X
                    // Always use the greyscale value for alpha 8 c! v0 F+ N4 @
3 V8 b& `, I  `. u$ n: R  b" [
                                        . k) \  h9 w" p" S# X& n8 C
- ^* o. x  v  x$ s# j3 z
                    *pDest++= *buffer++;//alpha! 我是一点不了解了为什么是这个? 8 ]* b. s! L- ]% H9 x
. ~' I- ~  f* @
                }7 }- \  V7 b) O9 @' d, g9 P* j1 f

% U; _4 N3 @- \5 ?6 W0 C8 F            }: {- V7 q  [! D& s
# Z6 h; g4 l7 f* w0 g
  / Q6 I1 p! Y- l' i& k3 J, X+ d) C7 S
- _  l. W- s$ \( j
            this->setGlyphTexCoords( i, - g! }+ ]7 q( u0 w2 m

4 e- ?6 p2 d; }) v2 R                (Real)l / (Real)tex_side,  // u1
5 P6 L: N! {4 `6 u) ^6 M! V0 \" ~$ W& I8 W# V& d8 y
                (Real)m / (Real)tex_side,  // v1
+ b& Z# j* e/ M' Z" v% h) Z4 B# [+ U' |5 N7 Q# {  Z! |' U- n
                (Real)( l + ( mTTFMsg->face->glyph->advance.x >> 6 ) ) / (Real)tex_side, // u29 H: L+ V$ ~- Q* b

* @! V/ g1 \1 w/ D5 K# s                (Real)( m + ( max_height >> 6 ) ) / (Real)tex_side // v2
4 d# _" U2 P, q+ `) k- P/ o7 _! i' {# s, q0 e( N2 a1 Q
                );//设置坐标 9 U7 ?- T" r, ~7 C" r

, d$ Y+ ]/ ?! ]4 n2 |( g  
, B- L: Q8 x. Q
1 g7 [' g' ~& n$ }0 K            // Advance a column , z' ?# w5 N9 g2 U
! M8 h8 X3 `5 A( |7 ]' \
            l += (advance + mTTFMsg->char_spacer);
4 F' j) }' v- W: h' u
; l& B; F9 X; X3 D6 V2 h                        //l+= 本字宽+字空
  s/ z+ u! X; z. C) U& r) Z7 |; y3 }( N3 a: U* m
  
: h; h9 ]& t" q$ E: A' @' |7 m4 a3 z9 e
            // If at end of row
0 w8 P/ B  F  C1 o" [0 z8 p, ?
7 a& j% L8 ~, @; ~                        //如果到头容不下一个字
$ G) K% N. |8 }
1 C: {$ s- p% y9 m5 ?' s            if( tex_side - 1 < l + ( advance ) )
6 X" ~: {8 X9 w0 I% K3 U) t& r' `) \
; F- ^) f3 j' I" H8 I% r            {
2 N8 w4 a& i: }4 z/ c; q9 o2 M! c: Y8 q, N8 \' \5 A8 k  b
                m += ( max_height >> 6 ) + mTTFMsg->char_spacer;
! G! p; o5 `$ O8 S. h/ I- t+ s+ Q+ x; e: s  O
                l = n = 0;
' x% n* G" u5 J7 Q8 `' \
9 k2 w- p" I. p8 e            }
# v1 Z3 }$ V1 c: v* P, R! u* k1 e0 ^5 \4 l( v; m, H2 u
  % S; \3 Q. ]7 A  F7 E- F
/ D% X# p  z$ r7 O) v+ C$ z8 [
        }! t3 |+ b9 o* i/ h
9 \5 P+ n# n- o( P' k6 ?
                // 把信息存到我们的mTTFMsg中 >_<
' C" W3 ?8 ]4 Y" |  T' y8 Q
1 f- ^7 L6 K) }% F& o$ P                if(l)3 R& P9 q3 Q+ J" e' z' c' @1 S3 L

7 y! Z1 L  h! R  A                        mTTFMsg->point.second = m + ( max_height >> 6 ) + mTTFMsg->char_spacer;$ q, \9 J' [' J) e

" D2 r. U% c- z* w                else # m+ n; J( b5 h' A" B

2 E9 p  k1 {; w+ V- ?6 g                        mTTFMsg->point.second = m;
  R7 `, C( Z% Q2 B0 B4 {
- ?: [. O  q- ~0 s  
6 Y) D' f" f! m' j" Y3 }
- v4 _. \" H! ~! N- [                mTTFMsg->point.first = 0;//另起一行
$ ~7 |. P' B3 ~+ h% J0 l
2 u0 O( l( f, `5 _# Y, l" }# o2 h  % _4 b& x* w% b6 }7 `( Q
7 P' y$ u' `- G  ?9 L
                //下面是保存几个最大。
. B) U9 @* H5 N2 R
5 K/ g# z- M3 B3 [* a7 {0 ?4 Y                mTTFMsg->max.height = max_height >> 6;
5 t! f% u$ }. `# c: |" ^! h! }8 z$ s4 p" K3 M: z6 l' x  |4 f
                mTTFMsg->max.bear=max_bear >> 6;
$ \1 `) m# n# D! z+ g
4 d9 y# [$ x' S# c( K                mTTFMsg->max.width=max_width;" L8 e) P9 B9 X) [( K  w
9 |% k2 K9 o- F6 S+ x, L
  
) {4 L" M# U+ f0 Y% l) d4 q" l0 h8 i' H1 K
                mTTFMsg->imgchunk.allocate( tex_side * tex_side * 4,imageData);$ y6 |9 H& s' x; I0 L1 `: }

% z6 P0 b7 I6 f, ?6 a- V7 S               
& K( R6 x1 y! B: l& e* `
+ k8 E+ c. z- K$ @( Q                //不知道为什么要设置img这个中间变量,似乎可以直接从chunk创建贴图 ( _# L! x5 W) [3 ^) i; f. L
$ k2 ]) S/ c( N8 \# c
        //--Image img; 7 s! Y7 X2 g3 v6 ^2 ~9 i
  V* W, M$ x/ G2 Q7 S; [5 K0 R
                //img.loadRawData( imgchunk, tex_side, tex_side, PF_A8R8G8B8 );8 s, u% G, ?6 |! R
- v8 J$ A. j# |4 N1 q
  3 P3 [9 |# k4 T4 Q( q0 {

1 {: m% U( p; I: I6 I, W0 r  ~4 Z! F                //贴图名
1 F! x& S: D# ~. u7 k* n) a! l* j. c: ?3 F4 Y4 u& |
        String texName = mName + "Texture";
/ r) W* \) `) ?+ S
! c( _) O" c- X. I0 q( G" v                // Load texture with no mipmaps
9 n; M  P5 W/ u/ L: Q5 R& I6 K, K2 @0 K7 P% D' K* K  D
        // 把从img创建位图改成直接从chunk创建贴图
2 I$ k1 X+ j, l7 V* E0 n1 V, u6 o! m) f6 Z
                //TextureManager::getSingleton().loadImage( texName , img, TEX_TYPE_2D, 0  );& s! q* F/ j3 e+ X
3 u/ g3 Y" T% G+ ]
                TextureManager::getSingleton().loadRawData ( texName , mTTFMsg->imgchunk,tex_side, tex_side,PF_A8R8G8B8, TEX_TYPE_2D, 0  );
% f7 o4 ~" B$ I7 f! Q! o% }" ^' ?8 X" w4 P% k% V" ~
        TextureUnitState* t = mpMaterial->getTechnique(0)->getPass(0)->createTextureUnitState( texName );
5 x3 |5 i6 V, a* P4 M
7 R: ?5 w4 C' W; K1 N+ c& ^& x, I                // Allow min/mag filter, but no mip " f5 u. j- V# T4 T$ R

& r4 f" m  t$ D! p9 g7 c                t->setTextureFiltering(FO_LINEAR, FO_LINEAR, FO_NONE);
0 q* v1 g& L) O( T3 |6 Q* D1 N& V$ N. e( j
        // SDDatachunk will delete imageData . h/ q& V8 R1 l4 N( U

) P# `: |: C' l  c. _- R        9 h5 L0 c! e: X4 N& x6 v. q# e

8 [& m/ m5 i* T- k) p+ x, Z    }
" h5 R" |7 I( o, m' e$ z/ }
2 G! }- q- |, o9 g8 J2 S5 @% R        你应该对照一下以前的函数,改了很多的。
& @' D* F* {7 f8 V! ^  h8 x$ K3 w' S3 ]+ I
  
/ g0 u; z) t$ g1 H) D8 }3 |
, R4 s# Y1 M+ Y" \$ K8 F/ r  
( X2 F" Q& H- c2 y$ ?  I9 A! c% I0 c0 x
(3) & [8 i- x' T/ }
" w2 `4 K. k+ z5 N: p$ q
        然后最重要的是动态的申请和画字。
' S3 H5 u3 k" W
% V* \  B: ~0 t1 S" C, m        首先最重要的是我们要一个方法得到汉字的unicode码,我们用到了unicodeMap数组,提供了区位码到unicode码的转换工作,等一下提供这个表给你,好不容易从网上找到的阿,可惜这个表没有中文标点的对应,如果希望支持中文标点,就要努力找到unicode码并加进这个表了。这个表是这样的 char c[3]="邸";unicodeMap[94*(c[0]-0xa0-1)+c[1]-0xa0-1];就得到邸的unicode码,不知道为什么没有5165~5169的unicode码,是轮空么?
* B% }7 k4 A' S, Z' Y% [% U# A9 W9 m/ n( D, u& g. C( V
        
  V* w8 l; L% K. R$ o5 a6 X6 d  Q. @, X& c6 p5 Q" Y
        申请渲染(字) 3 S2 I! m0 H" \" g- L

4 N8 f  A  c6 \6 S) ?0 B4 y7 f        {
3 T1 d2 B. _' ~0 F+ N" z
! y1 |9 H2 Y  Q/ g                if(有这个字)
7 I7 E  j2 E9 @' ], m# k8 X' a) }- d# l/ e8 B
                        返回位置 , H- z3 @) g  X% w! T

0 s, H* R7 a7 y$ K' t                else. s: n+ V4 c# t

! |! s! g3 j/ X3 \* |4 O- W2 }  P                {. a7 B" G) u1 A  g8 _

( m8 y$ J( O" j0 m                        if(有空间)
3 P+ h" N$ D8 e8 w/ r/ C5 @: l& ^$ z6 v  c6 `$ m
                                画字 $ c0 R8 D8 r  ~+ a! A  u

( Q4 X3 q8 k( p4 f0 v                        else* N$ q, s+ x0 y) ^/ K

( ?  Z. e' t7 s# H6 Z3 [3 o+ H: j                            找不用的字//找不到就出错,没地方画了
; x* j+ E8 T3 H1 F0 |" m/ d( z! s% N
                                删除 在这个位置上画字
" L/ L/ ]. A* s  i
* ]* r. [$ X; s9 o% v                返回位置 % J- d" i* n3 t& W/ E) P6 x
" F: c. E% O  m
                }
7 {' i! C8 [- Y# w' a7 Z6 P, X3 e. m* J6 J9 b
        }
2 h/ H! {2 B( N9 g# @3 b6 g: a0 S" \3 \! b
        上面很直观把,大体就这个意思了,申请渲染的函数是inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )  const。去掉const改一改。得到
1 H2 a5 x" ?: A) |3 m' v* C$ I9 I% s1 f4 C+ ]9 F' c
        a.申请渲染   ^  w; H, C3 ]9 T' r7 A# N

1 ?8 h3 {1 v# u& N; J$ B( k1 m! v8 J        inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )         
; _$ w! S8 C7 `" F, O0 D+ W, E( \
4 R' F) i+ L5 ?( u6 o        {5 f4 j/ C! b2 S

" F8 K- P! ]# ?0 ?: x" z                unsigned long idx = OGRE_GLYPH_INDEX(id);9 F& k+ o  X4 U$ ?4 e( Y& U

* b, ?5 ~& L" C6 k; r4 x                if(this->mType==FT_TRUETYPE)//ttf?) a5 y. @9 f0 Q% Z
+ A- o  J7 k* m" R9 y. F
                if(id>=161&&idx<OGRE_NUM_GLYPHS)//汉字?
0 {  U4 v7 `& B% e/ T  ^: U! [+ h$ k: z/ {' N: z5 e( G
                        if(!mTexCoords_v2[ idx ])//没有?* d2 d# r" j3 B+ A9 H
& ^! C% n9 ]9 L4 Z* x. Y
                                setChar(id);//画字去 ! |* _. q8 v( l

" f% x  @8 H$ K. X. n            
; M  b, R- T8 u" x- o, U6 a. b6 c3 L  X* Q$ W) L
            u1 = mTexCoords_u1[ idx ];
% E, @/ s7 n! {& i
- P7 p, B5 X; h            v1 = mTexCoords_v1[ idx ];
2 d( P" o4 V( E( a9 F
1 V: e) D( c7 M            u2 = mTexCoords_u2[ idx ];
! [  n- I# ~: A/ |# w& f7 `% C6 \$ i* ?6 r- L7 G' u! b
            v2 = mTexCoords_v2[ idx ];
1 u/ j0 R# H7 F: \5 E1 P, m2 ~
' Q( Q3 [8 W! P* p7 u+ q        }7 ^* E- Z) ]: F
9 U1 N1 u$ K: L8 ?' S' ?
        b.画字等 ; n  P. z- O9 A( D: {
0 g2 O) a( \+ C" E0 q
        bool Font::setChar(unsigned long dwChar)
8 N" T) H9 f5 O4 o  n% O/ m6 e; m/ ?  w, Q$ ?- t
        {
' [) C4 y( Q! ]/ i) R) o" E8 m; q0 X1 E5 U$ y; R$ C6 _" \
                int j,k;
8 ]3 q' t/ }+ z, `" Z. R3 a7 h7 `+ q9 \3 E% p1 |9 K) p
                uchar* pDest;//操作数据的指针
. Q" s4 P# a5 y( N/ ]0 ^, F' [$ y, b! C: l5 h6 @$ p
                mProportion=0.8;//不知为什么,总觉得中文都太扁平了,所以设置这个参数,在《让OGRE支持中文》中创造的参数 , m: i; S+ E0 E. G5 w
  N$ i* g0 s3 F) M& w# z
                Image::Rect  rect;//画字的位置
9 s, }( [: l; B. W& ^7 L( S" A* k$ u9 ^
                if(!mTTFMsg->getRect(rect)/*回头看看这个函数吧*/)//如果得不到空位置
# t6 S  U8 X+ u$ Y
2 @& g* D. T8 A4 Y; d                {
& Q/ A$ B# p% [5 s. o1 P* q& @' s9 D5 g9 Q
                        for(int i=161;i<OGRE_NUM_GLYPHS;++i)//寻找不用的字
" i+ E# t6 Q1 b7 d5 \
* d6 p1 g% l$ K7 c. G                        {
6 \7 k" d( f0 s4 k& {0 m  h/ J% C* e  e6 B- _
                                if(!mUsing&&mTexCoords_v2)$ Z. j- Y! S7 t0 a1 c$ K
$ \' ], K- f- ~! @8 l# ?
                                {  ?* o1 C, B# o* f
( v4 C( i( ]% W8 C* a
                                        // 得到坐标
! |3 j7 E! |, |' y" i9 x3 f* n5 L3 U5 d
                                        rect.left=mTexCoords_u1*512;
2 {* u: Y5 X7 l& j" ]# ?6 F# W
  v+ B5 ]0 a% f4 ~$ A                                        rect.top=mTexCoords_v1*512;9 }! y- t3 b; R( S/ V
$ I8 A1 p. a7 t$ t( O: i4 G
                                        rect.bottom=mTTFMsg->max.height;
4 z9 R' S1 y; S4 n) h; a* R; T% h0 Q
                                        rect.right=mTTFMsg->max.width;
' }8 \# D4 x) `2 D& _4 q
: p8 d0 k# ~# Q' ?  `  4 v: b" @9 C/ X6 I3 ~
7 s% w0 U% f+ Z6 X
                                        5 L! o+ k; L# X: J

. m$ z" Q. k' E9 b' z                                        3 c3 b+ h# z& W. v% y( }
7 L% e( `0 t  x+ I
                                
2 S* N4 J  u" l6 V* Z+ Q& }
( n- m5 A' u8 r5 n- L. d+ i                                        //擦除(这段代码没有试验过,等做完输入的类在检查吧)
% i& f  o4 y9 R% B4 R7 @7 w
% {& V2 d) r$ a$ W) W, j* u: ^                                        for( j = 0; j < mTTFMsg->max.height; j++ )" g9 p4 @7 l/ k8 i

! S5 D2 N* p. X! f' }                                        {
6 f" Y9 x! J" y" o& I$ S' J9 J* U  C+ M0 ~1 M7 o, b
                                                pDest=mTTFMsg->imgchunk.getPtr();
, K0 _, p) U6 e
- h/ ]2 c6 c" L! z7 {( R                                                pDest+=((j + rect.top)* (512*4)) + rect.left * 4;
% a/ ^7 M# l1 W2 C  X9 y( ?9 I% G+ T( d
                                                memset(pDest,0,mTTFMsg->max.width*4);* A' K5 x+ J+ M# N

) l( @  S' l, v                                        }
( R- V4 ~" i9 d. W; I. ]- `$ F
* K/ D3 Q* C) W0 [0 r! I7 z2 d# N                                        mTexCoords_u1=mTexCoords_v1=mTexCoords_u2=mTexCoords_v2=0;
: C4 s7 {, Q, R! g$ b" m9 q2 D/ F
* n7 k3 j; Q) c. L  * R( T2 X8 l7 [+ `2 H2 w' e$ J

0 N$ F  y$ e+ e- F4 S& o( o5 Z                                        break;5 x- K( W2 s0 l5 f& S
) U: x2 t! g0 W4 Q7 k
                                }$ ~6 ]- `7 J5 y" i
3 y- `8 w$ I# s
                        }
5 \2 a: m' a* d% W  t9 p. E
5 }% h) I0 C) e3 t* F0 \, K& N                        
, ?1 B, `2 Z4 F# _) U, p7 N8 Q1 E5 }0 T# t7 @  O* f  o
                        if(rect.top==-1)//啊啊啊啊啊啊啊啊啊,贴图竟然都用完了,没办法了,出错了
# I1 J, M& P! c& A8 O' R2 q. R6 E% G' x9 [  P8 y: _5 G$ o7 |
                        {; f6 q, Y1 [% c7 U( s
' H$ B6 Q. ^* j8 j" ]# Y
                                LogManager::getSingleton().logMessage("你太贪婪了,用的汉字太多了,这是对你的惩罚."); " }! z0 P8 X7 ]& }
$ d' Y$ [3 `* c5 i! h. K$ r
                                return false;4 v- l+ X- l' }+ b
; f' X( H$ D( Z( x6 Z& H" m
                        }$ u6 Q8 S# v& r5 S. C

0 _+ c% L3 l5 X1 y& ]1 a        8 s, Z: N" [7 M: ]

0 S  e, d' b8 p3 s% I                }" M; ?" b2 q! c
- O3 a! @* [+ d1 K
                        
  a  l+ L/ y4 t
0 m$ o/ a/ r/ }' e/ _               
- b, ~* e4 A8 p& X& I$ y4 a  _( V  D  w& l1 @: @
                  //以下画字的都是招葫芦画瓢的,
7 ?, I, R! Z% y: Z( y, O6 h* s7 V( }; Z$ Z, [3 }! j) k+ j
                  FILE *fo_def = stdout;
. }1 I- J" {! l* }3 _* S! z5 |2 J$ a& T( z+ g2 H
                 FT_Error ftResult;  H3 U- C, S4 u
6 f. v! d5 j7 N/ H6 Y2 z
  " Z) N' L+ i; O. f8 G* b( y
+ X( r- ~0 L) x8 \5 H
            // Load & render glyph : ]% }7 f, m7 u! _# C
& t/ ~! C; G9 F5 e# d
                  # v3 S$ d! @- R6 p
- S% O. f/ V* v7 h* n9 P% I1 j
            ftResult = FT_Load_Char( mTTFMsg->face, unicodeMap[dwChar-161], FT_LOAD_RENDER );//读取字体
- A  w8 e9 k& z, f
1 Q. p7 m0 r, l( ?/ V, U            if (ftResult)6 Z% x5 G4 q% Q3 u) S' a4 s
1 L7 ^1 V! v8 ^7 q+ y
            {( Y/ i; ]! p: D* o+ p

: t# S0 r. X% h8 f5 l+ q5 I                // problem loading this glyph, continue , z, C" P' ^. Z0 j" }0 ~

# z0 O3 n2 Z% O. |                LogManager::getSingleton().logMessage("Info: cannot load character " +) X, @! B  W7 _2 `5 g
/ m/ V1 @! K9 E% |$ _
                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);0 ^! m( {) f1 W
3 k+ C" n' I  Y, P2 ?* z; X
                return false;//如果错误跳过 , j! V" V! H6 J, F8 M1 w

: u& i: e' A1 O8 ~3 A9 y. l* @0 n            }+ B# O% I* u( R. H1 U* _# ^* |

$ k: R( k" c1 C  
' \! f" M& Z6 Z. r2 k/ G: v  `, F- h% Q  C
          unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;
. ~/ \$ c& i% \/ ], x
8 L- ^3 B- z/ W$ o  k+ a# |% |) p0 z                  // 位图指针
- ^7 f6 F. v, A
/ d, R- m+ W) l% Y2 |1 l1 w8 N4 j0 j            if (!buffer)
, N0 K, G8 d1 P
% h# ~/ ~: D( ]& b# W; D/ U            {4 C3 S! l" M& x1 Q
8 s: Z$ Z8 n5 W2 `0 P7 ], b
                // Yuck, FT didn't detect this but generated a null pointer!
& U( [" r3 V, a: x; ]4 W* _2 _4 ?' L) X. Q4 d0 |! `& d4 a$ s
                LogManager::getSingleton().logMessage("Info: 1111Freetype returned null for character " +
6 W7 o; p8 ^; G3 j/ }" A9 ?# [3 h9 z8 a  ]& B0 x7 }
                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);6 Q/ z0 l  j2 W4 o

% }! F$ v4 o1 g8 H' F- Q2 ?( o3 ?                return false;//如果得不到跳过
" h! r: D" l" @* i% [" i
5 _  J! a7 Z* B! |2 c+ D# m" z9 _            }
5 m- i6 {7 m8 X' A# t$ {/ c0 g2 Z( s
  
* {1 ~$ J$ `' p9 }  H  l; Q  B' ^1 F" C
                         int y_bearnig = ( mTTFMsg->max.bear) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );
8 j+ i8 Q1 P0 A# L# k/ j& ]0 ]6 p
$ w5 q5 h# J6 l5 j9 r! J/ @      
- j; c5 B- j+ K  ~; X& Z+ z/ {
                        
( q- G0 N' Y5 t; T& A- X
8 k( U3 K% g/ ~( R* c            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )
5 e7 o9 \0 r' v- ^( H& [5 O: ?$ l; @) j2 j7 I
            {
) D7 Q% A, R5 k0 t1 \3 ?) l+ i
& e& b: W6 C4 E! @7 Y                int row = j + rect.top+y_bearnig;
) |5 F/ y( b1 x; `4 y. t5 J' y# Z
4 C* x. z3 s* g. [/ B& ?                int col = rect.left;//列
6 C3 O: D5 D# Z! Y" e
4 K, k, p) V' i( _& h! ^4 I2 E                                pDest=mTTFMsg->imgchunk.getPtr();
* s' k* [4 R' o& U7 T" l  ]0 z  t4 d$ T9 z0 a
  
9 Z- J, w( g0 H# E
0 A  @' L- P6 ]  y& Z                        " I3 Q) o8 o; |2 q7 i
  H, \5 G# C% \6 G5 u7 @- ?! c
                                pDest+=(row * (512*4)) + col * 4;% @) |. {( t6 M

7 c4 g: l. I" C               for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//每行的点
# o0 F: |$ S  n( L
! K8 g- ?+ e6 C. Z- a: M  n                {
: G% `/ R( w$ _0 G6 }9 }6 l5 k% f  E, }
                    if (mAntialiasColour)3 \' H4 Y  K0 ?3 K( W! }

9 C( U# U- i3 T2 W4 J' z! k                    {
7 s# S8 V  S0 P9 Q; E0 K$ Z
  A% v+ L; c) R  L+ X) w, d                        // Use the same greyscale pixel for all components RGBA 5 c8 y: H- h: k4 C4 D, H

3 n/ r8 t5 E1 x" B" c. e, G# c  \                                                        *pDest++= *buffer;
6 s. t' ]; f+ p+ y0 s; C% O* m+ q! T& E
                            *pDest++= *buffer;( a/ e. s! s' t

1 R5 P# f& v) ^) |7 e                            *pDest++= *buffer;7 A8 i0 q/ |0 d( A4 Y9 B3 P) ]

- [. K/ E8 f4 K6 c& A& S' L  M                    }
  \2 B5 u9 t4 Z# g
9 {5 e2 y1 o) T                    else * s# U# n+ R& ?- p+ G4 d
/ E; W' s: N& o3 b
                    {
7 m4 {  V* p3 Z! H! e6 L7 i2 p7 T0 q5 Z
                        // Clamp colour to full white or off
6 I. V2 |6 a' ^$ o+ E5 M" J, _" m; q5 D
                        if (*buffer > 0)$ g/ \5 {% |. E/ o
7 h! b& ]2 j; }
                        {5 t# T" ]! G, h; d( E+ g

& ^; U& _% `" H# k% U  H- p+ Z                            *pDest++= 0xFF;) D2 Y  ~, O* `* C' N) o  [

- w! A% ?( P( P. V' s- W                            *pDest++= 0xFF;# O- d8 {8 J, M$ w) X
  ]# S$ z4 }' A- x' q$ u
                            *pDest++= 0xFF;
% w( y* o# N3 V$ g6 R0 l
6 _9 j! }$ Q9 z) _                        }
  i$ P$ N5 d" C$ T( i; x% F& `" ~0 C0 b4 D
                        else & D  m+ u( [8 g6 [4 ^

0 F6 C8 H+ V3 }3 _' ]$ j7 ?                        {
" a+ {) f' [) M; k6 U. \% i( b0 p  G7 q, S' |) N9 ^
                            *pDest++= 0;
6 j+ B9 H0 |, _6 R& [% |! f
( z  V- z# D% Z; w+ {" e" G, I                            *pDest++= 0;
* @( ?5 A/ g& D( J% a7 d* Y
0 ?9 ?/ u: y: f- S                            *pDest++= 0;
" Y8 `0 `; r7 ^3 q
+ Z- G0 {6 A( i2 {& A7 X4 i                        }
) V* A8 U" @6 @, Q+ l/ N! _; O7 g! E3 v# o; E
                    }
4 R. z7 f8 j/ c$ y" T" s1 l: Z4 n% d8 ], q6 ]; a
                    // Always use the greyscale value for alpha
8 s' H) j+ F2 Y# t  K0 F& ^0 K
: F4 {8 y  h1 R                                        ; N) ]; t  l9 k& k! h& M+ @

+ ~# X6 y4 a7 c! ~                                //      LogManager::getSingleton().logMessage(StringConverter::toString(*buffer)+"is cool");# N. S& Y, I% t3 S
2 p% C8 Q) d- r# F3 b  f* }
                    *pDest++= *buffer++;
- O4 {' u* J7 a# i: A' J+ \8 P1 j# i$ c1 ^9 S
                }) x2 i5 ^( E6 r  x9 s: Z, O

: k1 ?; W) W1 {+ |. N. @! @0 x                                
4 n% C# v; j! ~4 g6 t: H' b) G0 l' V1 O% u+ M6 ]8 t2 F% d2 B
                        }0 h/ O" p8 U  x& K! l

1 o0 D$ C  e4 w, Q! O4 h6 b                        // 设置位置 ' ~4 ?9 G2 c- @+ o

9 Q: o* W4 u1 L% Q! k                        this->setGlyphTexCoords( dwChar,
/ e0 G  u! g0 A/ t8 w* N! x; ?  E  j" Q7 n; n
                                 (Real)rect.left / 512.0f,  // u1$ M' O% D' t0 i  B$ e  V3 Y

/ m- y# v& N* k) k3 R                                (Real)rect.top / 512.0f,  // v1  d; ?8 ~7 N  ^: m' M( m
& m4 A# D  |1 r# b) O; P" |! [
                                (Real)( rect.left + (mTTFMsg->face->glyph->advance.x >> 6) ) / 512.0f, // u2: _2 z) H6 n6 E* b, y; s

; n7 ?# s# A" G: |; j" Y                                (Real)( rect.top + rect.bottom ) / 512.0f // v2
. G3 H8 D! Y& r: E# t! G) u* r
. f& z+ d, P4 s0 k6 E                                        );
0 F' W- A+ S5 b$ r
; {, B/ }' D) U0 ^$ j8 h, ~6 T, {! i+ w                mTTFMsg->dirty=true;//贴图需要更新
% B7 n4 Z) L; l; h- m+ ~2 }/ m# d1 y; {  `2 Z$ h+ }$ ~% C: b, @- r
                return true;! F: D, e, m; N7 q6 t

" F/ j4 H# E. {; i7 a        }7 l  I0 i. y/ J7 s* I
& [  h6 b4 z2 N: O
  - B' E$ Q# ~  |: i
0 J9 O, p6 d6 o8 c, r, B* {
(4)
% H4 v9 w0 I8 p/ ~8 X' l! o' c- g+ c" |/ {3 w
        松口气吧,繁重的工作都做完了,就是更新贴图了。
) |. x; \( I. ?% ~& M, ^, ^5 @% e6 \/ B/ N/ [2 w
        Font类中~8 ]* r5 E6 K$ |  K# _# j

& C7 a( q; h. o: V$ Z        inline void write(). p/ j( x/ E' V' p0 e

: y7 ^& s8 U9 z  B! [# J/ n9 u2 d                {1 b9 c0 Q; G/ b0 U, y* S, n3 |

4 q- E: G* L7 y" Z  W0 l7 N                        if(mTTFMsg->dirty)( ]2 @5 p% X" [; y- a

0 H1 N7 V) y) U$ d* A. z                        {      
2 f9 j; s, k7 M
$ x( O9 V  x4 j                                // 重新载入贴图,顺便说一句,类似功能的函数还有
" z9 ^5 K; E# g- N( ~! Z2 a9 B3 g6 H1 u/ i
                                //virtual void  blitToTexture (const Image &src, unsigned uStartX, unsigned uStartY)=0
2 t% s: |) U( o1 P& A
& k+ z. @( [" l  D' Q! G. A7 Y2 }3 V  ~* z                                //和virtual void  blitImage (const Image &src, const Image::Rect imgRect, const Image::Rect texRect)! O% F9 ]* ?1 d* s% e$ a8 {1 B6 r

4 Y1 g4 }  E6 x                                //不过blitToTexture()在ogre-win32-v0-14-0之前没有实现,没有尝试使用。 blitImage()就算到现在也没有实现。
. J) D0 w$ l: \8 F: w7 d, \
/ ]. X5 `8 W' e6 S# D" i4 j. r5 g  5 X- q, L" f& K/ }+ j7 B: x; }
% m% W# `7 l6 G# G; d0 Z& A$ H
                                TextureManager::getSingleton().unload ( mName + "Texture");
/ K( s, L( ^4 y9 V: P$ F% V
" N* }- e  m7 o; K$ \                                TextureManager::getSingleton().loadRawData ( mName + "Texture" , mTTFMsg->imgchunk,512, 512,PF_A8R8G8B8, TEX_TYPE_2D, 0  );, z- q" P9 y3 y; D; S
$ R7 p( r/ N8 v- l/ j- n
                                mTTFMsg->dirty=false;
& j4 n: c3 ?6 m0 H3 r# W" O7 p/ f2 a! t; J3 ?4 l' V
                        }
; V/ L7 H* U" J5 y4 l  \# X
$ Y+ [/ E; m8 T                }
" M1 I2 O- b* X: k/ `! C4 Q
" w) w! j$ i( @/ \3 t! A* k# @- R  
( f0 D; D- f, x2 i* P; r# l" w, n+ Q, r; z  R( Q6 T2 F
         在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。
. T- Z: S2 I0 C$ g, J* y% |! F
9 A' q# E) w" k5 J+ i+ U4 }  . J' ^% U8 [5 }7 I& K* X% r

4 K5 H# y+ r- O( R* `  8 e) f: _  o' ^) N
1 N+ T: M- F. H: ?" \
4.结果。 # x# [0 D6 ~& o: L1 R9 O

/ m% z/ N: F- X& H% ~3 G; \0 @        好长阿,写了好长。虽然多是代码,但写注释也很累啊。重温了这些天的工作结果。就像上一篇一样“在OpenGL和DX9.0中成功的支持了中文,但是DX7.0中竟然出现了运行错误,具体问题还不清楚,还望各位高手指教。”。不过本来OGRE就不怎么支持DX7的,不管了吧。OpenGL中渲染的比DX9.0清晰,是我的显卡的原因么?以上的winXp+vs2003.net+艾尔沙980se通过~。。 . G; n9 ~( X# G9 `8 }

1 n8 n9 H) D9 C4 j: i        顺便说两句,上次发表了拙作,没想到好多朋友和高人们找到了我。甚至联系到了一个南方的公司,说要做一个引擎支持中文的方面。但是卖完400多的火车票之后竟然因为住房问题作废了,5555,退票少了80元啊。还是自己差阿,如果再多学点可能就能要我了把~。努力吧,争取写《让OGRE支持中文》三部曲。
! y" l- @  e: n
* o6 R" S7 z' a/ b0 b* K: x        下一篇应该是《可以输入中文了》。
6 q# w( e& t6 o  q" w0 `& w
4 H: J( [3 a+ @- W        也可能写不出来的~~~~~~~~~~~~~~~~~~~~    6 A7 ~0 u. O. B& \; p

1 t/ Y. k0 x: Y, M    相关文件
, U( t5 w1 v7 `" F8 H* z
+ t2 R; Z  E, ^( ?2 J* C( U1 o. W    chinese.fontdef//字体信息文件 放在资源文件加中 4 s0 {2 n# o' S1 L  J
$ D3 T2 f2 n: O
    font.png//字体图片 放在资源文件加中
6 S! C2 t, Z/ T1 V! @5 Z1 t/ i
+ `5 g; G$ ^# W, B  6 B- d4 e+ P9 G1 j! M
/ F2 @. y; C) s" ]6 |% q' D
    OgreFont.cpp# c) {  l- w  H6 f  s

! Q1 a$ O) v; @! O) Z    OgreFont.h9 {& v: t& O5 A% u6 D+ D7 B# ^
7 I1 `! m" R& ]( q# y, n1 n3 I
    OgreFontManager.cpp( s+ |- a4 ^  y$ b
' _: a" y2 G" K. K
    OgreTextAreaGuiElement.cpp
+ E/ K! D' K8 g- [+ @- C+ z+ o9 P8 c9 C4 C: J) R8 k! t+ B
    //上面文件覆盖同名文件 就可以 先备份 2 O, ^" y0 I+ k4 [) ?( ^; e
( A& C# O3 R4 U+ Q2 R
   
; @: N  }/ q+ |0 v2 A6 n) F% k+ s* N+ A' v( I
   solo5.ttf//这个是一个中文ttf 我直接替换了原来的ttf/ L! N0 K) J' t2 [+ @: T" q* ^

+ K0 ?8 [) i  V& S$ O   unicodemap.h//这个重要,是换算unicode码的数组(文中提到)
. \+ D4 a3 K$ z/ W& W- l2 k8 Y% ^: u% \2 S: v' m  g
  $ v' K5 W1 U. i- b
( _0 s  R, z+ D/ _. N
这个是在ogre-win32-v0-14-0基础上改的(上次是ogre-win32-v0-13-1),
) N5 U6 ~7 O3 z, q
3 H3 j9 G) c6 j请到http://sourceforge.net/projects/ogre/下载 / c. z) Q. W* C# T, O# V
% A6 ~: c- T( }7 T
配套档案下载:http://www.gameres.com/Articles/ ... /ttf.files/file.rar : k  j- `8 ~( ~* i3 E9 ^

$ y: T+ Q% N- D9 |5 ?4 l" E6 k 免费打工仔QQ:1850070
( ?- p! F3 F& k  }- y; L" T: g( X3 P# l8 t& }
From: GameRes 9 K3 g- Z( K! W! |- p. G# c
! V+ E9 R1 n/ b4 D( r2 P5 [
http://www.gameres.com
5 m: r  F# ?" `
8 F9 z; Z4 I8 h: a- S, ^上面图中“免费打工仔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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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