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

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

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

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

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

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

开源的图形渲染引擎OGRE(3) --让OGRE支持中文TTF字体
0 e* [+ J0 y( z: j# Y; {1 p2 L% e! B
0.还是前言 ) m6 a. E  s- p. y6 H

  w% m8 h- ^6 ^6 S) L% A$ D        如果你希望能看懂这篇文章,请先确定你已经看到了《让OGRE支持中文》(http://www.gameres.com/Articles/Program/Visual/3D/OgreSupChn.htm),因为本文是在上一篇文章的基础上写的,并且假设文件都已经按照上一篇文章进行了手术。但是如果你只想简单的使用TTF字体,只要下载本文附带的文件,重新编译就可以了。
! I0 }  `( U0 r, Q3 x+ C1 [6 b) W7 S" E- a+ `. z( i# h
1.检讨 & M; _1 {' e0 q4 e
( q$ ]5 I  @, V+ q$ q2 X/ n) o
        正如上回说的,我们已经实现了一个位图的字体。但是当冷静下来思考时,就能发现这种方法的诸多缺陷。读入一个2048*2048的位图,等于在显存中保存一个2048*2048的贴图,不说是否所有显卡都支持这么大的贴图,单是每个Font字体类吃显存的胃口,就足以令人心惊肉跳。如果定义足够多的字体类,我想你的游戏的配置要求,在某些方面足以超过《DOOM3》了。
! |, r  f, X  T; X7 U8 l. i" J( A- w3 h* }1 e$ S( C. }( r. H
        而且这并不是唯一的缺陷,文字大小相对于位图大小比例相差太大,导致浮点数的文字位置误差很大,你可以在一个文字旁边看到其他文字的影子。(虽然可以通过增加文字间距来解决。)还有点阵字体本身的缺陷,就是字形单一,不适合放大缩小,一些文字边缘的马赛克,足以熄灭任何玩家的投入感。
6 r/ P6 i% r" B  J3 ^
6 y& E  ^. L& ^2 S, E        似乎TTF是唯一的解决之道。 & d+ w+ S7 M- M+ |( \0 o0 L
: k- S2 f3 C: C8 ?0 V% R+ ~& o
2.基本知识 ' o6 ]+ q% @7 b3 l9 V% I9 h( S! L

- J/ V  l+ o; V8 n- M(1)TTF字体。 : c' D8 |% ]; Z: W, Z
" s" A3 [" Y& T/ [
        TTF是一种矢量字库。我们经常可以听到矢量这个词,像是FLASH中的矢量图形,在100*100分辨率下制作的flash,就算它放大为全屏,显示出的画面也不会出现马赛克。所谓矢量,其实说白了就是用点和线来描述图形,这样,在图形需要放大的时候,只要把所有这个图形的点和线放大相应的倍数就可以了。而且,在网站上有很多的TTF字库可以下载,或者你可以去买一些专门的字库光盘。然后在你发行你精心制作的游戏时,可以顺便捎上这些后缀为.ttf的文件就行了。包括Quake这样的惊世之作,也都是用的TTF字库。 $ p! D# ]2 u: j8 I
; \/ k2 e# O" m% G
(2)FreeType2库
. {2 g" q; Z7 c# [9 v4 k( M0 O5 _3 A9 j: M
        在http://www.freetype.org,有一个FreeType的免费库,而且是OpenSource的。它目前有2个版本:1.0和2.0。其区别在于,1.0只能读取TTF格式的,而2.0支持更多的文件格式,在使用它之前请详细阅读所要遵循的Licence,以下是摘自FreeType2.0对字库的支持列表:
$ f: D1 z. T, I2 G$ u  T
9 g5 v% n1 h8 i, h* R  p        TrueType fonts (and collections) / j$ c6 X- a: q/ T2 `$ A' A7 G! `4 m
- a$ \, _* \2 G9 @& |* R  o0 h
        Type 1 fonts
" V% y  s9 m% T2 b8 L5 A; Q
- B/ r: g0 }! ]8 i1 ]; ?5 x4 g. l        CID-keyed Type 1 fonts
( K/ V$ `8 _; R7 ~3 w4 G+ [1 Y' s; s
        CFF fonts ; w' h& S/ L0 g6 M3 T1 y8 E
! ^  g6 l2 d5 \5 g& F) z" e
        OpenType fonts (both TrueType and CFF variants) 0 D* ^% ~9 ~! h, K  |/ Y1 s

  I& [0 t1 A1 u8 h( f7 K        SFNT-based bitmap fonts ; M9 r0 R. j  Z; {$ t
# }" |/ h5 ^3 P. z8 S( d+ p
        X11 PCF fonts
# G! e" ~. {# ?: n" ^* I7 y" V) L9 \
        Windows FNT fonts ; |7 ?5 @& A5 G6 u/ E

; i; ^1 H- s6 P9 F2 i4 \1 o(3)“主体思想”
' ]" ~* M4 A+ c. P
) @* P) M# Y0 x- q( v9 |        请参照炎龙工作室的《游戏中汉字显示的实现与技巧》这篇文章,可惜使用的是Windows API,作者千里马肝,上网上搜一下吧。
0 k6 `* M& o3 i# @9 ~# o8 E' V" r$ W/ k+ b" u6 S9 r
        附带说一句,上面两条都是直接从这文章中剪切下来的,>_<  不要骂我啊,不知道算不算侵权呢。 : k; S1 Z% }6 W
2 X$ \" O( h: J. E' C
3.动手术---比你想象的要麻烦
' H/ y9 ?' W& h! R(1) 1 O9 Q* V+ E4 W: s7 L
        首先要告诉字体类,我们下一次渲染需要哪些字。以便字体类可以在需要的时候释放不使用的字体。 9 f7 [. g/ C$ X. a* u7 V

- `- d4 ]5 D% @0 l6 i* B) h        在Font类中~ ) C% m) X8 C. X: v# t

$ w, I# s' G# X" y% ^        a.增加数据 bool mUsing[OGRE_NUM_GLYPHS]; 用来标记文字是否使用。
" ^# r0 \$ v1 R/ V! p; P
9 q3 C& w. B) [9 F' G        b.增加函数 ! R0 N  r, H" Z8 `2 x5 s; e' x

$ a" _+ v. h. D: H7 A                inline void setUsing(std::vector<unsigned long>& caption)
3 ?. c4 I2 _: [: e6 j- ]! E  U
# |$ n! `+ u$ T) n                {7 v' g4 K: P6 p/ J

' d- H% }% J2 Z' y  U8 n( a                        memset(this->mUsing,0,sizeof(this->mUsing));
, ^. \. h2 a+ T/ O
( P! [0 z' _2 ?" h/ z( U% B9 G                        std::vector<unsigned long>::iterator it;1 s: H+ E* J' K& D, @

0 R; I1 ^6 m4 c; T                        for(it=caption.begin();it!=caption.end();++it)# P# d1 G4 S& d- b/ p' |9 T
# |3 A/ _' T& \: k8 e- ~$ B
                        {
0 |0 n6 {1 r. v! X; @7 |0 ]# r3 A2 x0 q' {6 W" y
                                if(OGRE_GLYPH_INDEX(*it)<OGRE_NUM_GLYPHS)
- u9 e% v1 z3 Q3 W7 V& U: ^( Z# v0 c( ^$ a2 \  U" q. {( G" j. y
                                this->mUsing[OGRE_GLYPH_INDEX(*it)]=1;//标记文字为使用 5 |7 |6 `; x* n& k( E+ `
9 |7 e' ^3 a. Z, n
                        }
  H9 a1 x/ L8 M3 n1 H+ A) X+ P* m, N, Y, _
                }0 y0 h- A& ^5 b
/ S3 o0 \& A! }5 \5 V" x
        并在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。 ) O9 @% ]1 n' Y" x5 }* r. i
(2)
. |; E4 Z* l4 ~6 z/ k. e3 c7 i' c) Z- I
        然后是修改void Font::createTextureFromFont(void);
$ U, J1 G' k; b* W* F. O) s' `0 t6 u" {3 R9 S  E9 a/ \
        Font类是通过void Font::createTextureFromFont(void)来把通过FreeType2分析好的英文字画在一个2^n*2^n的贴图上,然后再保存英文字的位置。 5 L  x  a* x7 K( B. e4 ^4 _2 j- y
4 ]6 T* f: H% A( p; c3 a
        我们需要修改的是: : l: x2 k3 c4 ?7 T  ?% Q$ m

- @9 I# c% M, ]        a.从函数中分离并保存画字的FreeType2和辅助变量。我们通过一个类来保存和处理这些变量。 7 `1 T0 w* r+ j% o' o
/ n$ R8 M( Q" x7 L4 e. I
        class TTFMsg
' g( [0 [* U. K- H  V0 m- W+ R8 F& o+ D- V8 |# F5 F
                {
! N2 @0 t4 U( [9 ]
/ \6 ?4 C3 |: B6 f- @8 |" W                        class Max//类中类,用来保存几个"最大",7 b/ l0 h9 D$ F

9 J) @$ b( s0 B$ C! [4 w                        {  w6 X- k( u) S. n2 s

( [" r9 j( }: T) X0 \/ T( F# v                                int nothing;//这个是用来占位的,没意义,反正没他就运行出错,可能和数据对齐有关吧。 7 N* k( b- y4 W- F
* L) v5 ], X# j& S
                        public:
# }- t: ~; n% S' _                                int height;//文字最大高度
0 R' n) y& k; b' _# g* `" c) q                                int width;//最大宽度
: g8 r  Y4 y& s+ @8 k4 r                                int bear;//最大空隙?
. g# \- l6 O+ M5 J                        };
, k2 n6 z2 E! s2 T                public:9 k" }5 ^; h; u" T1 R, o
                        FT_Library ftLibrary;//FreeType2用
4 x. L2 u( w. l" C; ~. s                        FT_Face face;//FreeType2接口? ( C# e& o2 ]% L  d
                        uint char_spacer;//文字空隙
. [  Q1 e) y  ?3 c5 ?6 a                        SDDataChunk ttfchunk;//数据块,用来保存ttf信息
6 ^+ K7 M& X& S/ |  w  U+ m                        FT_F26Dot6 ftSize;//FreeType2字体大小 4 |/ O4 A, X7 R
                        std::pair<uint,uint> point;//在位图上画字的点 * D: N4 J2 ~6 a7 H
                        SDDataChunk imgchunk;//数据块,用来保存位图信息 1 U+ x4 ^- M; q  \; F3 \- ^8 i* H
                        bool dirty;//标记,看是否需要更新贴图 + C; ]9 D9 A" \4 [& N  X
                        Max max;//几个最大
- T0 B% q% Y. A
2 [0 i$ ], w' d" h# c                        inline bool init(Font*  font) //这个是初始化函数在void Font::createTextureFromFont(void);中调用.
6 X3 ?7 Q+ i& N1 J- o7 u2 t2 Z% [+ h- R* X/ }5 t/ |) _
                        {      
1 z+ v' `; o% o, o0 _$ s/ b3 g, [: [& \5 j/ S" S6 m5 X% @
                                //以下都是初始化,大部分都是从void Font::createTextureFromFont(void);移植过来的 / z0 c: |# c) E' t; p, k: A& x, w

2 f( t) L8 E  W. u% c                                dirty=false;" \" i$ @6 F: U7 T" M" Q; w
4 I3 C7 b, I2 x, U, q
                                if( FT_Init_FreeType( &ftLibrary ) )1 ]0 p% i1 {  i9 p) F$ \7 Y

1 V6 ?# D2 G7 B+ h0 v9 r                                  Except( Exception::ERR_INTERNAL_ERROR, "Could not init FreeType library!",) |! x8 i+ B% n# Z
. Z4 g! f) q, \
                                "Font::Font");: W; e- i$ r) L! P  F

3 f# ]% S. h# G* @                6 a2 [* V* I3 U1 |6 G/ w1 @) N- {

. }' u6 O, o- B$ b& A1 E; w/ h5 b                                char_spacer= 5;
1 q/ |% ]: Z; \. r) F5 S
0 ]% S- z1 e( F; r$ P                                FontManager::getSingleton()._findResourceData(font->mSource,ttfchunk);8 B  L( @& _' `8 A7 E
1 c7 e% h" m4 \& |; p- M
                                if( FT_New_Memory_Face( ftLibrary, ttfchunk.getPtr(), (FT_Long)ttfchunk.getSize() , 0, &face ) )5 p7 t  z. r' E7 B) V' K
$ D! ]8 }1 @8 G; F* s9 o/ T
                                         Except( Exception::ERR_INTERNAL_ERROR,
$ l: }  R. h( v
8 P( f3 }  }$ C                                        "Could not open font face!", "Font::createTextureFromFont" );
! O5 @: f  G2 |/ C/ o% W1 X' }' c. j1 H5 a: L$ u+ P
                                ftSize = (FT_F26Dot6)(font->mTtfSize * (1 << 6));8 L4 ]% s' P5 Z: |3 \

3 n3 r) |; }- O1 B) D1 {                                if( FT_Set_Char_Size( face, ftSize, 0, font->mTtfResolution, 0 ) )5 I& ^/ m/ \1 V5 d! N: p2 u

. w/ b6 ^. }% c0 N' `: ~& ?  h2 T1 Y" i1 u                                        Except( Exception::ERR_INTERNAL_ERROR, : f  O, x( D& c7 I3 {

2 Z2 ?: s- t1 @2 t                                        "Could not set char size!", "Font::createTextureFromFont" );
% a' u; U% p5 e
% a0 i8 a6 P2 p% W' S7 T' R* w; n  - M5 k8 x; c; K0 V; t: C

& c9 I9 q! N, O4 u                                return true;( J) Y7 I6 ~6 @/ U: j: Y. U+ b; d

3 e2 N' g! h7 e1 ]                        }% u1 U9 P& t; w5 M

& l) g% q0 D* r( j4 g3 A+ B                        inline bool done()1 d( d7 w5 J8 n& o, c5 v( I6 F

- x. F9 O0 d1 b$ j4 V% k' K& }0 x                        {5 }+ f, B7 |7 x

& p( Z* F0 U. M3 H7 c; k                                //在Font的解构函数中调用的,本来应该调用下面两个函数,但是不知道为什么一调用就出错,不用倒没事。 ' @& W& q& f  V8 A6 w" @
8 m+ T. d0 V6 P: J
                                //FT_Done_Face(face);7 d3 K) Z: `; H- F. L: A

) X1 A4 ]' D0 ]. s/ Q% }( \; t                                //FT_Done_FreeType(ftLibrary);2 [0 T- I0 o  f
& u/ v1 D$ E" a
                                return true;
' P$ C% U/ r% z' I: h& @3 y
+ X' P3 r& u5 v' {. T, @3 A                        }
  h/ o- e! J8 x( |+ L
6 |9 d( ^" v" i4 G1 H! \4 ^                        inline bool getRect(Image::Rect & rect)//这个函数以后用的,是用来找到可以画字的贴图的空的位置 - h+ w( i, ^3 V/ I% m8 `; P
/ e0 z+ D- R- I  }7 d
                        {
/ D: R5 ~. ?+ P! C3 x
: V, S5 k% k9 e0 r                                if(511<point.second+max.height+char_spacer)
' K4 u( O1 F4 n* H% A
2 g7 @$ C, y. M) Z& ~                                {
4 I$ P; `6 Z6 Y) `  r
# T- ^, ]! I- d, M( x0 T$ E- n                                        rect.right=rect.top=rect.left=rect.bottom=-1;
" Y# [2 f7 ?+ C
5 D; L7 B- t+ n: ^$ y' q" B0 k" y                                        return false;5 |7 ?! M7 v/ e4 x

! ]& [/ Q* {0 A0 E) l                                }
, x; m6 }: ^- Y( p, O
9 z! I: M* o: V+ j, }0 Q  ]                                if(511<point.first+max.width+char_spacer)
, F" K' N& a$ C( e4 X
9 v. F3 O9 z6 }  o) P" d+ }5 r                                {2 @( }6 K5 n# m9 u  o

, k- Y- {! J5 l- m! L& b' f, W( t/ I                                       
9 }" c+ d# K7 v) `) D; d$ a
8 a/ R+ M1 ~( W( e4 x                                        point.second+=max.width+char_spacer;# E1 `7 C4 e/ [" W& G) @
7 A  C6 L( W  Q' E  v# L
                                        point.first=0;& z% z7 |! R( n9 q3 _

8 Z8 W3 t5 n" ~, t$ }! H                                        if(511<point.second+max.height+char_spacer)' t' j+ Z( {, W6 b5 Z" q! G1 B

5 s, G, c. T: g# a" Y* G                                        {$ `1 }0 n* U0 v5 Z* k
5 W" g# N- s) H( ?; s) H1 X
                                        " p; a5 Z: X" O7 {/ n; ^
6 j  L1 o5 ^9 L3 f' I, n3 x1 r7 T
                                                rect.right=rect.top=rect.left=rect.bottom=-1;
1 k# }' k1 A9 ?/ T- b2 ^! Z) D: u/ Z- `( x( i
                                                return false;* |9 i8 \7 s* u! S$ D% }
! [, P% c% `0 Q7 e, t
                                        }0 l! l/ o+ f: O/ h; C

) S$ w: l0 a( L                                }
5 E' ^& n  n) H
; o+ C$ c8 {/ u$ _1 k                                rect.left=point.first;- a, B: n2 \! ^
5 n$ h4 @& H6 ^  ], v+ y# v. T" M
                                rect.top=point.second;
; o' I, s3 y+ M! t6 L3 k* o! ]1 z% w" T" v# v$ g% N/ Q* G2 M
                                rect.bottom=max.height;4 m% L0 f: x  T# ]2 }0 T4 {& i' d

) P; y8 r5 |( c% }. q6 v                                rect.right=max.width;+ L3 M# W1 h, U
4 q+ {7 t8 H4 @
                                point.first+=max.width+char_spacer;& H( z3 e$ j' w( L2 P/ Q% [
+ w: S+ B4 ~& w  l8 M
                                return true;9 U6 b. J0 l3 b# ?

, E0 ^: l- \* ]/ r7 S% m  w                        }
8 i, S: F$ s" D# p0 g5 ~/ ~7 J% Q* ]6 c( i, |
                };
4 v5 I4 @% A  b. v! A3 L: k% T7 A0 ^0 Q5 ^/ {- v7 \
        上面的类定义在Font类中,在Font中增加 TTFMsg * mTTFMsg 数据,并在构造函数中 mTTFMsg=new TTFMsg;
0 V1 Z. e6 [: `' G" J0 |. o3 b! [9 N, @: h9 e
        ; K4 F9 `% s7 I: s8 P

: _) ?' D0 p* |1 B1 _* h        正是修改void Font::createTextureFromFont(void);函数,主要几点,首先是分离出很多变量和构造到TTFMsg类中了,然后是贴图从2^n*2^n变成固定的512*512,为什么要这个数字呢,因为256太小(废话了)。能保证512*512大小的文本区不会出现不够画字的情况(所有英文+符号+没有重复的汉字),这个安全区域基本上是够用的。(什么,你要画满屏幕的汉字?哪你自己看着改吧。)还有一个重要功能是,要找100个汉字,找出最高和最宽和最大空隙作参考。修改完成这个样子了~4 v) K7 D1 C% ^; l( Z* b* M& E! k
# i% z" k  M0 m8 \+ G- b- R
    void Font::createTextureFromFont(void)% q: Q- n: P. J5 a7 P

$ p' \: j. e0 m' ]    {
$ ?$ u# _. T7 h5 f  m$ }2 g' E1 @9 x! j; U# m4 k
        mTTFMsg->init(this);//初始化FreeType2
9 q$ }" k9 C- A5 o9 K' n
8 ?6 b! N& _/ I        uint i, l, m, n;# T' E6 B# N( |  B0 y. @! u2 l) ]
) I- U: S& Z( {: G* \
        int j, k;
3 k; _" z- L# J' W4 |
+ k+ F! A+ B& o7 M% c+ Y  1 W2 v& C+ `6 L1 p- V2 c

. O7 s3 p% q! L6 ?       # y8 ~4 s6 k, W3 X$ y
9 [2 V3 d' B4 ?7 b
        FILE *fo_def = stdout;//啥意思?我看不明白 5 N# g8 M" m7 {+ R' k0 K- p
0 G+ f: j7 n+ C- H% E1 n
  
  w( O0 N/ i( l5 S( g9 s8 ^2 c$ h; ^- O! h4 z& ?# Y. G
        int max_height = 0, max_width = 0, max_bear = 0;% x8 d$ T+ s9 B& |. M* z, i$ @; E9 v

8 i! O) H: U  S0 |  ) V6 `, u( {2 Q% g6 L2 X7 U1 @

) b/ H& l. t: Y( C' E; j* k9 U" r        uint startGlyph = 33;
, S# ?# n0 U; e3 _3 c1 a: s+ n( ]
$ R8 S/ Z4 k& A. k" X2 U        uint endGlyph = 167;
7 ]2 Z* D" }2 _
5 ^- i6 ?9 t( w9 @' Q    |1 p, y: F6 G8 \4 g

5 }3 X9 r) J. @7 y        // 找英文的找出最高和最宽和最大空隙 7 N; o2 d& b4 C1 _1 k
) D7 i7 I- E! m' I  ^
        // Calculate maximum width, height and bearing 4 Y% w% m; x$ |. `- W

$ S( n. d! k$ P2 N        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )# [' ]& }* Y$ e
0 s7 u8 @* R, m8 Y
        {
* [. b( i& k& J4 h/ ]1 N2 x% Q/ D$ q8 @0 X2 c, d' b
            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );
5 G6 u' {- X( E" E! j/ l5 ]' Z7 o/ p3 x+ P6 ?' \. X/ s9 z2 N( }  B4 l
            //以后的 <<6和>>6都是FreeType2中的数据和我们使用的数据的转换
: H# ~, M' ~" B* M- q4 a% D  G" ~( F% }. }0 q
            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )+ n# s8 l1 _: f( h
: |# N' R7 b& o: K$ t' [' f
                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );8 `0 ~2 b3 y* H4 O  h4 E/ [  g

4 O: ~! |% ^" Z3 |6 P6 P  ?" W            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )
0 d. w7 A1 B, y8 r
* g0 \  O+ r  n  g4 [4 `, J( {                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;' C% t7 Z3 K2 u' j

0 r: ]4 X  b5 V2 r, l  
; _# ?( a( Y4 z$ K$ k- {" d
6 u0 N7 Q& c$ e8 y$ f7 B            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)
) E% @: h* v* t0 m# i& r6 H: l' z5 b" m! T/ e
                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
% o& O3 b, z$ g# J) f: ]0 o* `( J+ u2 P2 R, d. K, r
        }
& b- p6 x) k# D/ ]( _: b! g+ h" k& S1 o3 H( M+ o$ ]
  
  e) S( |+ c' [1 K# I/ M3 D
1 f4 J- B: l; l7 [  
; {0 ~# r# {9 r, M# w5 J  Q0 B* j" w
        //下面的for是找100个汉字,找出最高和最宽和最大空隙作参考。姑且认为最的汉字就在这一百个里了。
$ u' P. D2 T8 i
& w% I/ i$ n* b- O! U! j- T* h5 R- d        for( i = 20643, l = 0, m = 0, n = 0; i < 20743; i++ )2 ?- u5 B' q+ P- ?8 x  n6 s& P

% d; ?" f$ x+ d; k        {
5 G8 q2 @3 l' d* S7 a7 F
2 N2 S. E2 A! N, a: j            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );/ o" b- R# u  k/ m4 v

7 f+ G0 V2 a! _9 a8 K0 ?% V  0 f/ S. n0 f9 P8 F- n
* E2 s3 y$ [* ^: ^
            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )
) `" I9 s; I0 P- S
+ ]+ o) F0 h; j  p                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );3 @5 l7 I. L' N

# B& ^. Y: S7 U6 s2 E            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )6 d! b$ F8 ^6 V( J

$ t5 |2 d% t7 a1 R; i                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;9 y7 C& `5 Q) j! G& ?: d0 y
8 D1 q2 V6 y3 `/ b# J3 z1 |1 F1 \
  $ e, p. i8 k% D7 w1 }
3 `( n. m  y6 D
            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)
, _6 H7 {! A, O
& |4 d: ~  M" F% i( a                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
" A" D6 k0 J* g/ u: b  n  ~4 z; J: p8 W+ \# a( r1 p7 v& X
  
8 ^$ g  h& L; @4 ^- _: s; Z/ X4 o
& D4 w1 n6 N4 B! P                        
8 u% b. X! D7 y* H$ }, G
. M; _$ W- l4 _+ i* r            if( (mTTFMsg->face->glyph->advance.x ) + ( mTTFMsg->face->glyph->metrics.horiBearingX ) > mTTFMsg->max.width)
. A* j5 H6 I3 c
  ^/ m! _# V8 }2 a" Z' l% b                mTTFMsg->max.width = (mTTFMsg->face->glyph->advance.x  ) + ( mTTFMsg->face->glyph->metrics.horiBearingX );
" C) E9 p4 C- R* n2 ?3 n8 q# l- k. b
        }
2 K0 E+ u1 R9 \+ g: R2 j% u* W/ A- w) s- r
  
  W' A" c" x7 V
9 ?5 H3 }. c0 \6 C- |$ \( G+ i                //下面几行行不需要了 我们要512*512* n: x8 @6 s; X, `: J
! Y$ y8 c0 _. a# ]
                size_t tex_side=512;//就是这个了 5123 n2 c: m6 u2 {+ @: M' ]

2 q& k' c( u+ ^: R/ L        //定义数据宽度 因为是32位的位图 四个char为一个像素,为什么要位这么大呢,难道不能用8位的么,我尝试着改来着,不过改了之后就不透明了。望高手看看能不能改。
3 G: l9 J! h. B5 t' Y
9 J  D, K6 v7 N6 X7 D, P3 p/ |* Q                size_t data_width = tex_side * 4;4 l* b9 Q5 |4 h2 N
6 M: B& e: b, t2 t
  4 {# M5 l( A' _5 s! D

8 A2 n  M9 U. e1 `' s$ f                LogManager::getSingleton().logMessage("Font " + mName + "using texture size " +( l% h% P" M4 K7 T" z0 u. F; i

+ [( |/ f& b% D9 N6 F/ R                        StringConverter::toString(tex_side) + "x" + StringConverter::toString(tex_side));   o0 c6 W. j+ ]- I) U* W+ J3 a" y4 @

4 \1 F, q3 v! e/ `3 E0 K' V  
* A# F5 j- g; G1 ^
" T0 u, i1 Y* m7 X# H; v8 {) t& ]        uchar* imageData = new uchar[tex_side * tex_side * 4];//设置一个空间用来保存位图
9 J, m- |) K$ {# W5 T7 J( e4 O3 T6 n) }' k! W% k9 t
                // Reset content. J# E' L) @* ^" B

" J' h# z3 y- v: ^                memset(imageData, 0, tex_side * tex_side * 4);//清零 5 F1 F  C! O+ Z1 T1 m: o- y
* d5 G# L3 y4 a+ K4 E
  4 A* F( T" s1 b6 h
: Q  N' }/ y% |" p, }3 h- N
        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )//遍历每个字,
( k+ z: x3 s: ?+ D3 f8 _, @
% ]8 t; M. D2 R        {3 [' ~$ l1 x7 ?3 }

+ Y' Y& l: k1 M( J                        
5 T0 R: }5 \$ K; r0 V; I/ E( B# D5 _# r* I4 ]% H0 e) M) U) ~
            FT_Error ftResult;
4 v; @! `1 G9 }" A0 T
  g: j  H/ p, s. w  
- t- }3 ~8 }, h
  `8 r8 R7 d7 ]: j/ F            // Load & render glyph
, O' r1 b2 L3 j/ N- z- r; F7 F* n6 ^  y4 `" }* O1 @2 i
            ftResult = FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );//读取字体 1 C& v6 R# c, k
1 Z- V7 t: \& k7 K9 h0 K: H" L+ X
            if (ftResult)
* T/ t1 g& k' G% R7 I# X3 C6 C6 U0 o* \" B( h$ Z
            {8 b$ V  f3 F/ r$ g- V% f% y& P# U
, l7 }  k$ Z) z+ b4 W* N
                // problem loading this glyph, continue
. B6 c/ V: Y3 C0 D8 k' W8 n; Y+ [. S% k1 G9 A
                LogManager::getSingleton().logMessage("Info: cannot load character " +/ y! j( {, U2 G- g2 T
0 Y" m" M: v  R$ \! b8 h
                    StringConverter::toString(i) + " in font " + mName);+ q* V& _# a8 i/ i, z5 ?

) _4 D- }* A% R' Z2 a. V                continue;//如果错误跳过
: K$ ]$ a' d% |1 L" l! T/ Y" w+ ^
6 J/ |) }8 A" X4 q! [            }
2 Q, M5 M6 d! Z! [
( Y. l+ X) l$ E; M( w  
3 G9 l! w6 _. d8 ?& b- ?
/ y* N1 F/ I1 F0 J6 Y. g                        // 应该是字宽 8 u- V  _9 h9 N. `: {3 W$ H
, D' e: f  j) U4 a" p
                        FT_Int advance = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );: O  q2 j6 ^. M" q, S# L

, u4 H) H* b5 w0 f! S4 g, w! h" W                        # [( `0 d+ P+ e7 v7 W: M
8 u. D) p) m3 @! r# h
                        // 得到FreeType2的位图
9 y* B& W( f4 J( N- c1 H: U% p- Y4 O; n/ f
            unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;
5 S. H! u  t: {# i
* @2 F2 x4 Z% d6 S" r1 o/ w  - h; ~8 E$ S: K) I( h7 w
5 s1 i5 i" ?# t4 Q$ Y/ l1 }
            if (!buffer)! I4 b/ _' f8 k  t: P
9 N3 j$ J+ s) P$ X9 ^) c0 Y, g. x
            {& Z3 k0 Q& u* p- `  G0 K

, S& V  r5 L: A0 Y# {                // Yuck, FT didn't detect this but generated a null pointer! . l% w" Q: N9 w5 E; N; Z
. {9 E9 e- E7 i9 s7 a' w4 R
                LogManager::getSingleton().logMessage("Info: Freetype returned null for character " +
6 p% t. e; ?2 b0 a3 q5 Q, X4 F5 ?( W1 y- F3 S, V( I
                    StringConverter::toString(i) + " in font " + mName);( {/ o. O- N$ \( Q8 d/ w
' V0 e" ^* e4 ?* r& S
                continue;//如果得不到跳过 7 U- Y. q6 x8 i% t! O, s
, P7 O) S& w- k, r0 Z* Y
            }
' N$ V2 b* _; c: C  A$ t0 e8 i# t. ^7 z! a
  + G( |2 n' v- V: q# P$ D2 z
  x7 [# g, l3 g! G4 g4 Q8 z
                        // 得到y的空隙 (最大空-空-本字空)就是说空出这些字底部就平了
, q) ?, s! |" O
6 X4 |# h' k, \+ `4 o            int y_bearnig = ( max_bear >> 6 ) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );+ P( [+ p2 q3 @9 _6 [! n

4 d: o6 y  m- l( M                        
9 ]; x' d3 y* P# [  ~, d6 U$ F  h, g( B6 m$ }2 Z+ t. V, k
            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )
! O8 p" q2 P) |' U9 a  u5 L' [, `6 V
            {
& |. g' H: K4 Y
. u% b& h7 g$ ]+ B                                int row = j + m + y_bearnig;//相对行+本字在位图的总行+空隙
$ V7 k3 b' ~) g$ Z/ v/ w3 o- J* i6 n$ l, G
                int col = l;//列
# h+ T6 S" h0 I; i% K& r5 \1 U
* }( k/ x5 e% A% L+ a3 ]$ T! {/ ]: a                uchar* pDest = &imageData[(row * data_width) + l * 4];//找起点   
" w" l5 w: Z4 ?, t$ `( ^/ ~$ H
' Y2 n: e7 c& I% C. r  ^2 @* _                for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//画图
; M4 J# g5 c/ c, h# B7 }# X; X7 E; y$ |9 P- j
                {
6 R9 V3 f4 H9 _3 V1 @# @  v4 n+ T
& x* X; Z# B* }# y                    if (mAntialiasColour)//看不大懂,难道是灰色字体? 6 m  H4 a1 r: w
0 g6 C$ n/ l: v7 C
                    {  N( |$ N# X. @" g6 A" C: w% A7 E' ~

$ s( N7 `% V& w! R/ ?0 L5 b                        // Use the same greyscale pixel for all components RGBA 6 o9 g3 E; s! F
5 F  Y$ C" \) {0 Q2 O, _' q5 p
                        *pDest++= *buffer;
1 v8 g8 ^3 l6 G/ P+ G4 W# G2 M! Q2 B4 Q9 H4 d# H' ^1 h6 Y+ [
                            *pDest++= *buffer;
- U( i4 a9 U2 o; V( ]& D1 N
3 ~' E; U, t% l( E4 D                            *pDest++= *buffer;
1 R2 q6 Y+ N' F  O, D  v! T0 H# @* C3 j- Q! j0 @4 Q! |
                    }
$ M9 |* {2 q9 G
1 N% ]6 Y$ L7 a% L* ~; F' `                    else , b$ g7 U2 q+ O0 i4 [# c
  R5 V/ G( D- E  }8 o8 O
                    {! b& s8 ~/ F* }, D  |

0 v7 x" J) Y- A; M2 `: x7 u! p                        // Clamp colour to full white or off # o& L  ^* |: r* e3 W
: p9 }7 e. x( ]8 h$ u7 c
                        if (*buffer > 0)
. l" X! O; e' S; e4 y* x# Q; m
/ b+ P- @* f, t# o+ W- T6 M7 I                        {# l' @6 [+ z3 J

( d, Q1 l! f! l( O& U( E" R2 }                            *pDest++= 0xFF;# F* R0 }9 a% h* w4 b% J2 u$ l

. ~1 M" r' e: Q2 c                            *pDest++= 0xFF;
# d3 s9 D; u( ?: n- Q: R) u% G1 u' y6 f8 c) i3 k
                            *pDest++= 0xFF;
0 C- A# h  v# C( m9 V7 F/ C+ x7 M; a$ i! @# M# r" t
                        }; l6 S. l7 o/ k& \4 ?

) S8 b. m! ^2 e- `2 \                        else , v" A7 Y* r, N' k" @- x! b

, L) |6 Q7 W. u# Z+ c, T4 X' Q                        {* S' L' W. @. V& h/ i! I5 i

7 E5 {% u6 X4 j9 w- E" {+ `                            *pDest++= 0;
* @% \7 |( R: ?
6 i7 O# }. [. j  ^; ?                            *pDest++= 0;4 X7 H6 H3 R/ Y& D, C

# _. I" F' x/ }- }                            *pDest++= 0;
7 W2 v" B6 R6 l7 p7 p: J: v$ b( M# q
                        }9 g6 T* ]' C. c9 F* |! ^" {

" u% u6 Y! v8 k, v1 A( p/ ^, B5 B1 E                    }- \; L- K4 ?) f: T

' i+ O" V" U# [6 p! j, D                    // Always use the greyscale value for alpha - }/ h' @+ T$ v2 ?- U
6 f! i! |$ q: r) {
                                          j. H5 t/ H3 x# Z
1 j. j1 A( g0 v* P5 M& h* D
                    *pDest++= *buffer++;//alpha! 我是一点不了解了为什么是这个?
, o% Y- g, ]* }0 z
' o0 c7 _' ]6 o" @" E                }
0 [( p% ^" v0 t8 H; B
; r' J( a$ Y$ \            }
  t! T; f. U+ M) v" a
/ D7 Z# f( A) ]% d4 L- V) B  |& b# Q  
) u) M' |/ D' T% C; S0 @" m- y
            this->setGlyphTexCoords( i, + ]# M- L( Q( w% x+ V( f* z

4 E& m: g$ c- ~% q9 N' F                (Real)l / (Real)tex_side,  // u1
0 X" w; b! i$ S; F8 p& Q1 u
: x; h* H2 r/ T- @                (Real)m / (Real)tex_side,  // v1
( k% u# E- h. i6 }1 ?9 ^5 F9 D$ R
& D: g( j4 ]# e* ?7 _0 `8 g                (Real)( l + ( mTTFMsg->face->glyph->advance.x >> 6 ) ) / (Real)tex_side, // u26 v. \# F2 @5 L$ K

# z! `7 x. ?% l6 J                (Real)( m + ( max_height >> 6 ) ) / (Real)tex_side // v2: a# @+ }( {+ k! j" X" j
5 i' W  o4 ^4 T* Z
                );//设置坐标
7 `8 s5 C" @3 @' [5 j) b: y6 ]8 Q. I( v$ G7 @8 t8 L1 }. w' P
  
: r' {" Z/ H: ~: \  n
; O4 q( n7 z) X, V3 w# z2 B& @& s            // Advance a column ; W" H  K7 T$ v% K+ h" q2 s6 v: G
0 k. n3 U- \8 j. S( s3 M+ T. e* Q
            l += (advance + mTTFMsg->char_spacer);6 j9 C8 H' _0 @6 ^9 k

8 D9 Z7 W  P5 h6 j4 q2 U, t  s                        //l+= 本字宽+字空
0 m( O+ P. `' y4 X: P
0 I9 u; M: P* [' Q  % T6 k. E, Z' \0 T" t0 c

  M* O# Z  B9 o$ A+ c- b8 U* O8 h            // If at end of row 0 w& S+ @* F7 E. l

7 f/ q1 ]4 b7 |7 n$ g, w                        //如果到头容不下一个字
- i# @8 X0 i* z; i0 k. l7 ~3 J/ |, X5 z' ~5 B* H- t8 F
            if( tex_side - 1 < l + ( advance ) )# J6 l$ d( t8 z
6 n' c- r) c7 e: o+ O5 k
            {
1 `7 t4 |. ]5 W5 q; N5 k* L
, h" W/ A" c" \4 }( e& ^6 I                m += ( max_height >> 6 ) + mTTFMsg->char_spacer;
) y: ?1 q) ~2 a6 d0 k, e' w& I( V. |: s% z5 X# f0 y3 h
                l = n = 0;
; O  A/ F4 _+ m6 y7 w& c: @6 _% K
# T5 J6 f" j" u9 C* X9 D            }
' Z) G+ j( T) b4 G- R" s7 A
6 _+ R3 A$ s  {; {! y. D  
. v: M# B9 G: E
; z$ L9 Z( [; W/ [& f" J        }
, E7 d# j5 ]* u6 G0 s0 q- E/ @/ d( x$ ]
                // 把信息存到我们的mTTFMsg中 >_<! o/ l* B- p* A7 O$ C
9 W) b/ D5 j. |! \4 k4 q
                if(l)  ]1 w8 O' S; O2 z

, Q# i! e$ x' q& F) u" W                        mTTFMsg->point.second = m + ( max_height >> 6 ) + mTTFMsg->char_spacer;4 P, R; f" J. V4 h: ]- K4 q0 M

( l, X1 b  \) C% R/ L' m' |* N$ u3 g                else
. M9 y. A- i: W. ]+ m* ]
9 o  \2 _5 X2 d3 P9 [                        mTTFMsg->point.second = m;& N5 v; L0 ^# T) I& A( t) J

: j1 L7 }& C$ m7 n4 h/ t- T  1 q% o. j6 t: c# m1 D8 ]

9 K9 A& x6 ]+ r& a                mTTFMsg->point.first = 0;//另起一行
" p9 {$ m" i& V2 p! \( _/ F% P5 y: V' Z  o" c) L1 S) V) {4 r0 e
  
- M. J, i1 _4 d: _9 ^
" y3 |# Z/ O# W                //下面是保存几个最大。
  [! O0 [8 j% M1 ?2 @" o8 H
0 d& N5 C0 w6 U) E  R- ^$ M- j' |) I                mTTFMsg->max.height = max_height >> 6;7 |8 o" a- @& o% B+ P
$ X' W$ v( n4 B# n- h
                mTTFMsg->max.bear=max_bear >> 6;$ M" T1 O6 P) ?, C: {, K3 w

& m1 ]  e: I" E, y                mTTFMsg->max.width=max_width;
4 c2 U" b+ C& ?/ X+ b) z) z, H) j5 e5 C% Z: @) [
  - P& X$ u3 c' u8 ~
" h  J  B. y! F! o! c  ?
                mTTFMsg->imgchunk.allocate( tex_side * tex_side * 4,imageData);
5 h7 V& }; a) k7 C4 j1 y/ Y* I4 x/ Q# G
                : c# e# z# w  v" m- y4 D/ o8 x. H
: m# S. Y' `) @% ^( E$ ]* ^
                //不知道为什么要设置img这个中间变量,似乎可以直接从chunk创建贴图 0 {. b7 y- _6 f/ r5 F

: O7 r; P9 i; c        //--Image img; / w" {5 ~8 O7 k4 k
$ `8 u+ E. k) }* w
                //img.loadRawData( imgchunk, tex_side, tex_side, PF_A8R8G8B8 );
6 s. {* A& C, _
1 n- l' P& ^4 f- ]" g. j  
2 I3 m" b; M( n0 p
1 b  d5 c" i/ g2 r                //贴图名
% u  U) S1 N+ e% G, F3 Q, u8 u. ^
        String texName = mName + "Texture";
8 Q" ?& n! W. E0 T, }7 t+ ?
7 P* ~2 d8 f, ?/ i/ W# \+ I                // Load texture with no mipmaps
4 Y7 m' }2 B! Z& E" j7 o" T; Q9 u% h6 P, d) @* U8 ^. H+ O) f0 i: ~+ q  @
        // 把从img创建位图改成直接从chunk创建贴图
1 H; L/ R2 j# w( W( B+ H' e$ `8 t3 {, m
                //TextureManager::getSingleton().loadImage( texName , img, TEX_TYPE_2D, 0  );
7 v: i. x4 u$ N' n8 ~  C- ~( M- c
* G) k( `" J+ F                TextureManager::getSingleton().loadRawData ( texName , mTTFMsg->imgchunk,tex_side, tex_side,PF_A8R8G8B8, TEX_TYPE_2D, 0  );
. J4 T. z9 d; v* Q2 D  c/ z! l, R  o+ r* b# y) h
        TextureUnitState* t = mpMaterial->getTechnique(0)->getPass(0)->createTextureUnitState( texName );2 ~4 j& I. L3 N8 Y' w, L
; O6 r3 N$ _( S, l3 b9 ^  J
                // Allow min/mag filter, but no mip 9 K0 b. S8 p! U4 E( X5 ~
) P1 y# |. ?1 A
                t->setTextureFiltering(FO_LINEAR, FO_LINEAR, FO_NONE);
  P7 R0 L# T5 H0 C( R  J9 L1 r6 R
* ~: \" @+ [9 S" W5 _" X  G5 b3 `        // SDDatachunk will delete imageData . W9 j+ W# g9 E' K3 g0 l  T

" T' F# }$ f5 w7 V        
; Z+ s" W2 p2 D/ e6 t* J
8 ?) C# X4 i% L0 V% H  a4 s; ?4 u    }
7 z# i# e: [' }
# x7 t+ ~2 g' d" m, j        你应该对照一下以前的函数,改了很多的。 " U; h, Q: r2 _' J$ `( I7 C
' D" }7 H1 \& I$ u* k  r( }
  
( o2 b4 ^0 U; ~- c7 u
4 R  V& ~/ `8 k9 S9 q" q  
# |* i, ?' f) E6 v8 n* |. _$ m% {' l$ w' G6 D1 ~
(3)
2 _, o2 l$ b2 ^* A
+ k2 g$ k1 T* `- Y# H/ |4 ?4 g        然后最重要的是动态的申请和画字。
0 Q' {( p9 u" P- R1 E2 ]
- b; h! |! h1 ^# V) S6 H& U        首先最重要的是我们要一个方法得到汉字的unicode码,我们用到了unicodeMap数组,提供了区位码到unicode码的转换工作,等一下提供这个表给你,好不容易从网上找到的阿,可惜这个表没有中文标点的对应,如果希望支持中文标点,就要努力找到unicode码并加进这个表了。这个表是这样的 char c[3]="邸";unicodeMap[94*(c[0]-0xa0-1)+c[1]-0xa0-1];就得到邸的unicode码,不知道为什么没有5165~5169的unicode码,是轮空么?
; P; f- x9 S7 \* ^. O7 i/ p9 |4 [, e  l4 ~2 g8 j7 u! ~  G
        
( S0 L# M8 e% V% q" A! ]  u  V  ~4 g3 c1 ]. I
        申请渲染(字) ( m7 Z! G3 I' u! n9 h% h
+ u; U/ D7 ^1 S( a! R
        {( J; e% k* h! ^: ?, h* P* {+ }
+ H9 g% m' b+ O- [8 I4 X
                if(有这个字)  e4 L: q6 i; H) C. s. J

8 x, e- ?/ p) A6 v& Y% G: Q                        返回位置
3 O' e: N: b* V6 }' {5 k$ D& t8 ]7 l- L
                else
* ^' f" a$ @0 T1 L7 w. N' n2 n0 W4 A) B8 E- Z
                {9 {2 z: f, `# @6 B, A
6 o$ }0 `" f) ~) ^6 Z& h
                        if(有空间)
  b/ P) F3 t' t, H) D; w- W, y" g0 W2 z
                                画字
; d' f8 F2 M. R9 k; q) S
' P) q/ N8 g4 k5 e7 A                        else
  p& _' @) j1 E& N% a) Z; E! ^; N+ S
1 n4 [/ T5 m6 z2 a                            找不用的字//找不到就出错,没地方画了 / p7 v! O: R9 r( [4 X

2 L' g: k/ V: `& l! u$ z9 p$ E                                删除 在这个位置上画字 - c4 V. ~2 H! @. V' F( u: m
% Q7 U  l$ q7 W5 o7 h6 Q
                返回位置
: z$ b3 o  }/ R; w
; C  B* i" ~7 j& X" K                }
8 Q" Q8 u& I) H& _, g- O/ K7 ?& E) T8 i- ^, G! p
        }" l6 S6 g6 ^' t6 \+ d7 P+ r6 O/ Z: v

& k+ ]4 ~0 U# l6 F% \        上面很直观把,大体就这个意思了,申请渲染的函数是inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )  const。去掉const改一改。得到 7 M8 }! A  q. Z) `* P' j
6 U4 t$ W% m" j7 E
        a.申请渲染
" g& D2 }! A% [9 a( Z# @7 x+ `
& ~6 `' q( c' E: C        inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )         
4 C' T6 l) M' G. ^
* |/ W7 Z0 M5 y2 i        {
  C0 s5 x7 {) |7 L: v+ L- d" S
& Y1 e" ]3 Z% v8 `                unsigned long idx = OGRE_GLYPH_INDEX(id);
: J  m1 L/ a' u4 T, j
( a5 F* t, P0 e  f5 D                if(this->mType==FT_TRUETYPE)//ttf?
7 G& W" f- l  W1 t: o0 s) U8 x7 [7 [) ~
                if(id>=161&&idx<OGRE_NUM_GLYPHS)//汉字?
6 t! `4 S" p5 }. r8 T1 Y7 j/ t) X4 A% l) e
                        if(!mTexCoords_v2[ idx ])//没有?+ f0 B0 k' @( k

* f# F1 \4 `/ i$ C5 \- {                                setChar(id);//画字去
6 a  r$ @5 E; Y: t) S) l+ z$ o" k* A0 g: d! ]
             9 h% `& G: Y0 i& l/ R" v# u
1 X: b( D" {$ R0 z, U/ H- X
            u1 = mTexCoords_u1[ idx ];
3 n# n) q# s2 U  P" e, t1 s7 H/ @/ w5 h( X
            v1 = mTexCoords_v1[ idx ];
- j* {8 h, D' ~% T# h6 u5 o- p+ D$ |7 `9 f+ E* U0 Z" u" L, d
            u2 = mTexCoords_u2[ idx ];+ p! A5 k% d  E4 N" d, `6 [
0 L$ ~( B. }2 ^3 _+ j
            v2 = mTexCoords_v2[ idx ];. _  L- E% H7 i- f+ p

- w6 M1 U6 X6 \( |, O7 _; r) D        }
, Z. C' ~( b6 G' ?3 D3 a& @: i6 f$ V" r, q1 G- t4 l' q+ \
        b.画字等 3 H0 n5 t4 \4 f' U
: i: S2 ?  l/ R, l
        bool Font::setChar(unsigned long dwChar)
7 @% d* H5 S- G+ N" Z! `+ F# E- k3 x8 R' K
        {
  n+ h2 u" ]9 u/ a% h4 v
  K2 e1 A/ M. K0 z1 @                int j,k;
$ D; Q7 o+ Z: u3 y! n9 X9 P
8 A  ?9 C/ A9 C$ v+ ?& H- a                uchar* pDest;//操作数据的指针 - L: k# F4 m1 p; I/ M

/ f) T) _) p: }  _& a6 w                mProportion=0.8;//不知为什么,总觉得中文都太扁平了,所以设置这个参数,在《让OGRE支持中文》中创造的参数 ! E- D) l% V! m/ s$ h4 W

1 g+ Y/ ]! R# m6 t: ~5 |                Image::Rect  rect;//画字的位置
) r: E) j  b1 Y; s( m. W. ^$ D, |
                if(!mTTFMsg->getRect(rect)/*回头看看这个函数吧*/)//如果得不到空位置 8 F) R8 m" P- i: K8 @* A8 K

- y! J9 G- F2 f9 y                {
0 B7 s9 n9 B1 j( |1 e" n
* t% s, y/ q: J& _                        for(int i=161;i<OGRE_NUM_GLYPHS;++i)//寻找不用的字 2 c# @( F- i# G7 w

$ X9 p2 S3 U) ^+ c! e$ l                        {
# j- v* _) m# P. R2 [$ ]( N
4 J( B1 t3 f( |9 i% D: q                                if(!mUsing&&mTexCoords_v2)
  m. ?' W) F5 x, Z+ ]- y' |" ^: a, S( A+ ?. y6 x
                                {  x3 b2 N& M6 F/ D6 M, e; E% d
1 W( F/ v1 Y: U0 D: Z0 i8 Z& [
                                        // 得到坐标 3 t; J2 k5 ~& y( N" D
" l* ^  q+ n& j1 @+ D$ [3 }$ x9 b) j7 M
                                        rect.left=mTexCoords_u1*512;: v7 k* f/ `, f* P

5 F2 ]! @! p/ ?; h7 i! h7 ]' `1 n                                        rect.top=mTexCoords_v1*512;5 y: F  N. j6 i

1 D5 u- }* b# i$ V                                        rect.bottom=mTTFMsg->max.height;
2 K" J* q4 h- e( C5 L0 p2 G' H( w$ |: c( A6 I
                                        rect.right=mTTFMsg->max.width;
3 k! Z$ K$ f$ j+ M# I/ Q$ x! ^- M* p7 J5 H% |
  
# j) L  c$ u) ?( o
4 `" ~2 b1 m0 b) Z                                       
( {2 M& [7 M' e# ]4 n% ^& [% c) M. K/ s2 k+ e/ F: c, w& G
                                       
1 ?$ i4 J5 I0 o* C' j& b
# J' p1 c/ A% q9 S                                " L, v# t0 P# {9 S
) g0 o) e8 c, P8 O% {
                                        //擦除(这段代码没有试验过,等做完输入的类在检查吧) 2 U% H4 k- [% Z6 ]& h
# M1 i+ [, _" x* O& s9 L/ b! H6 |. U
                                        for( j = 0; j < mTTFMsg->max.height; j++ )
$ B5 S5 k+ A* N1 g; l. A- {
. ~! Q$ A5 U# ^9 I                                        {
* y. B! U# B1 v: ?1 U* q
5 E1 K) y& r; O! b                                                pDest=mTTFMsg->imgchunk.getPtr();
; }+ R; X/ o2 T: X
" E$ b( k, s  s' g2 i                                                pDest+=((j + rect.top)* (512*4)) + rect.left * 4;
2 X% s' z9 j& I. R+ l7 Q: e0 j/ U( r# A' `/ O1 J% l# r. |; @
                                                memset(pDest,0,mTTFMsg->max.width*4);; A4 h( m! e  K8 b2 `
8 }/ M* }. \8 O
                                        }
' f$ G3 k, @8 w! _* b( ^( Z! V! m: W& q; n0 Z
                                        mTexCoords_u1=mTexCoords_v1=mTexCoords_u2=mTexCoords_v2=0;
+ A7 Y/ o9 f: J- {9 b* p) t
. H% P3 U, W6 ^! S/ G  
- [7 {0 a( L6 V# }4 N1 n- n( X9 r
$ h$ Z* w  h. L/ s# I4 m' a8 C                                        break;8 K- \! ~. Y4 h* j8 w7 b- m
' o: G& i" o: ]8 T" H  s- V. J
                                }) X) a6 U; A; d+ `) x: b
2 E) Z' k+ B2 \; h% i& e2 G
                        }$ o$ W: K( J' e, y/ t& k& B
/ K/ e4 p8 {  _+ E7 O
                        
  |' d2 ?3 y* M+ z9 L( A3 a& V$ }' i# Z8 o! l3 q& W% e
                        if(rect.top==-1)//啊啊啊啊啊啊啊啊啊,贴图竟然都用完了,没办法了,出错了 4 m0 O( Z; [# p8 a0 y

/ ?5 g2 a1 M  M2 S6 Z8 F+ C                        {
4 z* R* v: y1 i% `9 F+ B: |7 W# ~) T
7 ?8 s  ]- F/ e1 i5 Y! V& l                                LogManager::getSingleton().logMessage("你太贪婪了,用的汉字太多了,这是对你的惩罚."); 5 Z1 v% x. @; I: s7 m3 n0 N# x

* |4 P" M* w8 B# K8 D                                return false;+ ~5 H: y2 ?/ U! ^
$ {1 L: N- r4 Q: w
                        }
7 j* n1 S  }' U- G% q9 M8 H, m
% k7 y9 N8 l; a, w. c% Q        6 n+ a; |/ O0 ^$ K9 O3 |4 s" a

, k4 g2 I: K  h7 r                }
9 G" P& l2 w" ^/ a; A- K" @. p1 C
                        % e4 C8 b4 J9 s5 z4 N3 F$ N
4 q  U1 H$ d! T' D4 R  {
                % ^: C% l9 C* g% b& t+ n1 w3 G

) T$ C5 r$ }8 }4 |& B; [' r                  //以下画字的都是招葫芦画瓢的,
, j( x; {/ k3 I7 r  K7 \1 k
, J- T" z( V3 f+ U' i                  FILE *fo_def = stdout;
; J/ A/ }( s5 E3 ~- r5 l- C( S  P6 D' ?! {1 |: O
                 FT_Error ftResult;
! C: b# K2 L9 F! A- w" R' ?& q9 g
  
8 b- b* z7 j$ k. k0 r' x* u1 i# y6 B( c. s6 j; b, r7 O/ l! P: `" ^
            // Load & render glyph
8 ]. y, E! {# U7 v+ r
. k# c5 O. f* L  V5 z, |4 I                  
- U0 e; Q( {. a- N0 ], X- h. l6 ]$ r6 G8 q
            ftResult = FT_Load_Char( mTTFMsg->face, unicodeMap[dwChar-161], FT_LOAD_RENDER );//读取字体 . _( o! [- v% v/ a7 L

% \7 v4 w0 K4 K7 g& W% j/ v            if (ftResult)
) S9 X# A7 n3 o& ?6 l0 o& a7 V2 V$ h6 f, t! }4 a0 k. B# c1 b* i
            {
& v! w! q7 q$ B' }1 K" v2 W8 ]0 X' W5 d3 A6 w7 T/ o
                // problem loading this glyph, continue
, T' e5 p1 X3 }$ p8 K; A7 t
* T. {5 J) P1 @7 K# ]# l6 `                LogManager::getSingleton().logMessage("Info: cannot load character " +% H: w0 f& b: e4 y

+ T7 s) b/ u4 h" }                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);( K2 m+ O, ^: F+ N  O1 [
; I  O2 K% R# `5 x; v# W9 D' P& v
                return false;//如果错误跳过 ! i9 y7 @' q9 e
& h+ i% z4 e+ G3 V
            }3 ?7 k* M$ C( N5 J. o
6 z/ ]* t9 Z' a: D: [
  9 @' n# Q& `$ z7 \% B
9 G( T, l6 w4 o& _. d# t
          unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;7 A( c& e+ Y# v3 i5 W0 @
: C% o& t5 C6 h: P: H+ ]
                  // 位图指针 ! a0 w0 d2 Q; \; a

2 M  u! i% M/ D% n' T! z  _% y            if (!buffer)
/ Y9 d7 @% u' V
: u( k7 s1 v: f9 r) e0 n7 A            {
, ^# E8 p/ l/ L; w/ `2 |2 a  W/ ^* ?8 N$ l
                // Yuck, FT didn't detect this but generated a null pointer! 4 e4 P$ v3 H  U1 n& j  _

' q, _2 h& _, T/ f2 a9 w                LogManager::getSingleton().logMessage("Info: 1111Freetype returned null for character " +
5 |% U$ B8 S& S: r' w2 f' _$ t
# s, D/ q4 v& E3 t                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);# R# a; u; m- P* T5 w. l
3 P0 P  p$ n3 P+ n' j$ O
                return false;//如果得不到跳过 1 F2 N: z$ p2 b4 w1 X" Y1 Z

  \  F  y$ q7 V4 Q2 T& _5 {            }  m: h5 f* p* g9 M) j
+ `7 b  C# V2 t+ Z2 u4 t* c
  4 Y. b& O& |6 U& ]) b4 A2 C

6 T7 {' }1 ?# C1 J! d, }1 i! s; Q                         int y_bearnig = ( mTTFMsg->max.bear) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );" c% t. q, K! S. Y/ u% l. i
& o- |! x) i. Q3 S0 [- D
       1 W. D: \! a3 z
) ~, G, _0 X% V4 O* L7 R
                        8 R! x- o/ J4 D: |# {4 F0 o
; R& R& X* Z% Y2 n! q
            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )
, _$ y! d5 i. E1 Y% E. Z2 d- J
0 V7 \! p2 J# W( I" S            {
' x- k' i* S1 M4 ~- r8 R
" o  |9 i; z% O8 B                int row = j + rect.top+y_bearnig;& K9 |' w* ?1 F# }& \
& I! C6 Q8 _; }' q) S1 h$ ^0 c  T
                int col = rect.left;//列 " R# j3 M9 A& X  h) J" M. F, y6 @
# @- g' K; x. C& r$ C6 P+ B8 T+ q
                                pDest=mTTFMsg->imgchunk.getPtr();! s/ I( ]; ?" j' c  v
* u+ z+ A" X6 u; a; \' j* L: T
  
. D! W( z, I8 X4 ^4 |  ^' |+ G4 h6 h. m% l' ~2 J9 l" L
                        + g( [* m6 L; t: |* o
0 e1 t. N3 ?/ v* r2 j. |* t6 p$ U
                                pDest+=(row * (512*4)) + col * 4;! c3 R2 D9 [  t, ?

, {* h* w! p8 q9 c' I1 A               for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//每行的点 " O% z6 A! f/ `2 u9 {$ w, G1 I

* i: b, S7 N& y1 u; ~) N6 k/ t                {: t4 y) F- k  f4 O# p5 \& U9 R* g

1 ~0 P$ Q8 L$ b1 L                    if (mAntialiasColour)3 f  y. @& t0 L5 o, H! l. N# W
4 T4 Z& y: Y+ \8 [$ \. B: n
                    {
7 O! L! B: c$ I% O5 V% q! W
( f' n" x) L, o                        // Use the same greyscale pixel for all components RGBA , {% s7 y! _6 c" q' N
1 m* v  ~+ j! k+ z' m+ Y% q- g! ]
                                                        *pDest++= *buffer;
' l: q, X' T5 s( P3 Q
7 s* e" c9 Q% q6 V                            *pDest++= *buffer;
& w4 g" S' U' E( ^; t& _, m/ Q5 H/ J' @. T6 _2 H  T6 D
                            *pDest++= *buffer;
* a( r! A; v; p7 h" e! B1 A9 {
/ N& m# K+ x& [  J6 s                    }/ s6 ]) u- z3 t

; P! n8 L  d3 r7 g                    else
+ v0 D, e  }5 B8 n8 J1 I
" A7 ]( Z' J0 S- ~7 A: n                    {& E+ f/ c% N1 o  |0 Z

4 q9 ^9 P. {) U, J9 P, `! o                        // Clamp colour to full white or off
) v& H7 V" h4 {( l
' j! `0 ~" U" ^* n* y% g                        if (*buffer > 0)+ M; x" t. T1 j) P  X- f% p

' S& R9 T) u! ?8 c+ |- S4 b                        {5 |0 L8 e3 W5 w0 c: F( t4 K7 Y+ M
4 u" I" X/ |% m. W6 Z! a
                            *pDest++= 0xFF;7 [- M" H/ ~8 v$ s& |3 l( N: k; y
0 u+ @. \" c# C4 z6 o8 V
                            *pDest++= 0xFF;
$ P( W/ ?* H( S( }. `, z* M
7 y) M3 |2 M0 P3 R                            *pDest++= 0xFF;& k- v4 l; f/ Z! ]

1 |/ s( d& X; O                        }
# s1 A2 _2 ]& w$ L/ H% S2 k" U2 i1 ?
5 B( i4 G- X) @$ a# }' u                        else : l$ i: G( O9 ]4 Z
1 y/ F) N3 l  ?* I: [
                        {5 E2 E; Z$ J* F( h
( A1 [$ i# j( Y( `! ~
                            *pDest++= 0;
/ b* W$ b9 ]+ h' o" o, ]& H9 ^* h3 ^
                            *pDest++= 0;  p( [$ i: k! ^2 w$ ?8 C
5 ], Q( M7 F- e) o
                            *pDest++= 0;8 B8 l$ j8 P% y5 O
2 f6 q: e- }5 v) G5 k3 p
                        }! ?9 E, A. t. i5 X

( Y# K0 h$ D  c                    }
5 P* |+ l9 \: R$ h' Y7 i( s) v) Q" i2 c! T& d
                    // Always use the greyscale value for alpha 4 G! D4 V2 c8 P4 n- x

% `; \. F1 Z8 k% N. v3 q% M# G6 }                                        8 j9 J. \4 C8 J/ z% L
7 A/ ~" f+ Q5 t' Q
                                //      LogManager::getSingleton().logMessage(StringConverter::toString(*buffer)+"is cool");
1 R! O  Q- {2 q! N! N
' Y, l1 U5 k" M4 \( T" e, W                    *pDest++= *buffer++;& n; v9 B6 g6 m- ^. ^* {

5 w; k0 O6 a9 G9 l+ ?4 D3 C                }
" d; N3 g2 _6 R1 P. L6 Y8 k3 @1 v" K, L) D+ D9 G6 g# q5 K
                                
+ L$ n: g0 D1 j
. ?4 B" C; c: W3 R# V) h                        }
* T( y6 ~! D2 n' S/ C( E
: c; k: `$ U5 s) X1 w                        // 设置位置
1 n+ n0 n( Q4 a4 T8 J7 q* s- x: m$ }* n! B" k3 Z# f
                        this->setGlyphTexCoords( dwChar, $ H  t5 R$ S, K5 j* Q# a' X

9 c5 H8 A/ }: N. W% }, T                                 (Real)rect.left / 512.0f,  // u1' W3 w& @% f0 F+ }7 E5 l
; C3 F1 |( `/ P9 K: R. K" I; G
                                (Real)rect.top / 512.0f,  // v1' G3 b* K" c, H# h
1 |, D3 z0 U. g( l+ W% q
                                (Real)( rect.left + (mTTFMsg->face->glyph->advance.x >> 6) ) / 512.0f, // u2
4 c1 n8 B5 |$ @: V
/ ?# X9 E. S6 W) r& @0 H                                (Real)( rect.top + rect.bottom ) / 512.0f // v2
# M1 Z( t- c9 U& E; M% @' {3 ~+ N. W/ k5 f7 [
                                        );
4 x- W. H( V* O% A# k* e) ]3 U7 m. ~5 s
                mTTFMsg->dirty=true;//贴图需要更新 ' A  i( l" i1 X9 ]1 W
/ a; s2 ^3 l6 i0 H5 P7 k
                return true;  {: r% K1 X$ b1 J4 p& q
4 {, f5 _5 |7 [# s) m( D
        }
$ F, M' w7 U' M/ Z! {4 `* G3 F% g5 a" O- D* v. n
  
9 Q+ e, O( j, N! Z" ~+ D
& ~) w3 C; x6 {5 ?- j8 ~(4)
) v' [4 _3 J8 m; u, T6 }3 R+ c6 ~' N" d( E2 x6 `- n7 p9 Q
        松口气吧,繁重的工作都做完了,就是更新贴图了。 4 j# X$ g7 n5 i" y& u- v
6 [2 b, \' Q9 n
        Font类中~5 n% o1 G( F  |2 X3 t

  ~) a" q6 S: H% h: j3 X        inline void write()
' I# i4 L. C* g- U% B# j3 U
: j/ z7 [$ `& g4 b- Z/ U" x                {
( T* P( i" W, A1 O* y" {; [( K1 S. z4 x' u" o2 R$ Z
                        if(mTTFMsg->dirty)
" D3 w$ i, C0 n  L3 z% W4 o! ~4 I* K' X
                        {      
! {9 f- ~: ?/ C5 f9 t* u% c# g$ m8 [" N
                                // 重新载入贴图,顺便说一句,类似功能的函数还有
9 i+ p7 Q7 Q) E3 z* j$ S$ p' `  j% @' v* r5 ^. b( B
                                //virtual void  blitToTexture (const Image &src, unsigned uStartX, unsigned uStartY)=0 8 m/ P+ q7 O  g. t) H" L
, \5 f& I& _$ [" R4 O6 N
                                //和virtual void  blitImage (const Image &src, const Image::Rect imgRect, const Image::Rect texRect)8 x& d% v6 i. `$ _. m1 q

4 l3 p7 a8 }% h  }9 H, e5 m                                //不过blitToTexture()在ogre-win32-v0-14-0之前没有实现,没有尝试使用。 blitImage()就算到现在也没有实现。
/ P$ r) j1 V' P2 S$ V* `) y0 ]6 ^* @/ z$ l" R. W
  
9 a6 Z5 t2 u2 W  O+ y; l. v% S; d+ {$ g
                                TextureManager::getSingleton().unload ( mName + "Texture");
, ~6 \! l# L0 u/ A
! j; w8 \" P) x( T3 s( o; x3 A                                TextureManager::getSingleton().loadRawData ( mName + "Texture" , mTTFMsg->imgchunk,512, 512,PF_A8R8G8B8, TEX_TYPE_2D, 0  );
& V% @; [+ u1 P8 I- K; O: G
. G0 [, v, E6 C, j$ t                                mTTFMsg->dirty=false;
' q; {6 V: `, B2 l5 f8 V) Q+ a* M
3 g  l5 S7 R* f- ]7 P1 l  r  [( t                        }7 _$ R; Z% w% Q0 ]9 `

  T1 C9 ?* v0 _. @                }
, d" k# l% s1 C
& I# V) h5 }  A3 ^5 I  ' k3 |' Q4 ~; v. w5 {7 o2 x6 [3 ~: w
( T" a7 X$ F; a* y! Z
         在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。
  O* s4 O5 }  W: k2 F! \" E6 {: P% o* |* q) w
  
6 ?$ h! m0 w$ t1 K$ R& O! ^6 f4 Y* |* h  B  l: k0 O$ \, G$ H
  
9 h3 j7 W8 C3 s3 f6 g- Q' X3 D1 O1 W# v: Q
4.结果。 4 F% C' K7 u. q( |6 W

6 i$ Q( a; X. s+ ^: x$ i) [3 K        好长阿,写了好长。虽然多是代码,但写注释也很累啊。重温了这些天的工作结果。就像上一篇一样“在OpenGL和DX9.0中成功的支持了中文,但是DX7.0中竟然出现了运行错误,具体问题还不清楚,还望各位高手指教。”。不过本来OGRE就不怎么支持DX7的,不管了吧。OpenGL中渲染的比DX9.0清晰,是我的显卡的原因么?以上的winXp+vs2003.net+艾尔沙980se通过~。。
7 c; h, s& Q" h& m8 x
3 O! V' z6 @. x/ F  C        顺便说两句,上次发表了拙作,没想到好多朋友和高人们找到了我。甚至联系到了一个南方的公司,说要做一个引擎支持中文的方面。但是卖完400多的火车票之后竟然因为住房问题作废了,5555,退票少了80元啊。还是自己差阿,如果再多学点可能就能要我了把~。努力吧,争取写《让OGRE支持中文》三部曲。
( w% {/ B/ b* i8 D  f4 {# L. {$ _
/ k6 R6 D" N! b1 b% Y        下一篇应该是《可以输入中文了》。
8 X7 v; W; Y8 ]9 H& f
1 N- d4 v! f6 B        也可能写不出来的~~~~~~~~~~~~~~~~~~~~    2 S" `3 q& |1 X6 C. @9 F; a

2 }, f0 `5 y. B9 r    相关文件 $ J6 [# E# {/ L
) c) P7 I% y+ j4 B
    chinese.fontdef//字体信息文件 放在资源文件加中
% ~3 J& ~4 P+ Z% b0 q+ K
0 k* q& \) d1 h( m    font.png//字体图片 放在资源文件加中 ( [! e- ^, c( C2 A

  O+ l2 e9 o6 U0 y8 d* U' P) F  
! n' y+ n: m3 B/ c/ \% l9 N1 K& t9 l/ c
    OgreFont.cpp. o& \5 C# n$ C7 {& N6 D: K9 `
, x0 a; A* a/ X+ @" Y. i: d9 ^; l
    OgreFont.h! t+ T; L3 G0 {) b3 v  ^3 F* c4 h

2 z) y8 T- d6 k+ Q    OgreFontManager.cpp
, l' h. r  C3 r5 N" b( R2 a
" C, y1 j6 P* A; q    OgreTextAreaGuiElement.cpp
8 X* A$ J( _( b: ?+ v- z3 r$ K" z( H2 q. y0 X
    //上面文件覆盖同名文件 就可以 先备份
6 H, k3 _$ ~' D  g9 {
; ]* h. K" S( r1 Z9 o& r7 p   
! r6 _- ]! Q1 z% L4 Z) z5 }
. z( U" T) n7 K, M   solo5.ttf//这个是一个中文ttf 我直接替换了原来的ttf* @: F  {. f% G" k9 z' Z6 G) ]
6 g! W, n+ A) L; h$ R$ b3 y
   unicodemap.h//这个重要,是换算unicode码的数组(文中提到)
0 D7 S& y; k3 m4 H0 x# R' e
; @$ I! \$ b8 a8 j  
+ O$ h, k: M3 x  D, V' K) j, j( |' b/ {& T7 _, E: F
这个是在ogre-win32-v0-14-0基础上改的(上次是ogre-win32-v0-13-1), 0 y2 u) }1 m4 B( d2 l8 k

$ Z7 |  s( K) t$ r! t% ^请到http://sourceforge.net/projects/ogre/下载 ( A( S# ~4 p# D" _. m, e. ?+ {( |

) \1 m+ H# ?; q) q- @! O! @) s配套档案下载:http://www.gameres.com/Articles/ ... /ttf.files/file.rar * o& ?* N4 H9 G6 D

3 h; F. F4 I+ x( ], V- b  ^" j- w  | 免费打工仔QQ:1850070
& R; _* G$ J& u% V) \6 R- g% d8 v$ n9 {4 `. B& r
From: GameRes 3 G8 G1 ?! k: z' o. d

# b6 R+ }# o2 ]6 o0 Chttp://www.gameres.com7 A$ z. W( Q6 b# {& G
5 r0 c6 r1 b  {$ B8 W) q# u- M
上面图中“免费打工仔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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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