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

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

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

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

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

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

开源的图形渲染引擎OGRE(3) --让OGRE支持中文TTF字体3 {3 Z& W8 E" u/ G/ H

) ^2 k) I& L: V! W2 [0.还是前言
0 ?. X) P7 L9 D9 R7 F2 J* O* g( I" N! y. g8 i: H! P4 O
        如果你希望能看懂这篇文章,请先确定你已经看到了《让OGRE支持中文》(http://www.gameres.com/Articles/Program/Visual/3D/OgreSupChn.htm),因为本文是在上一篇文章的基础上写的,并且假设文件都已经按照上一篇文章进行了手术。但是如果你只想简单的使用TTF字体,只要下载本文附带的文件,重新编译就可以了。 2 g2 A* O: M/ w1 J4 W( ^
1 c! @. j5 F0 V0 l+ Q
1.检讨
) z" k8 ?' g  O* f
& \& n" |9 |2 `9 s* G        正如上回说的,我们已经实现了一个位图的字体。但是当冷静下来思考时,就能发现这种方法的诸多缺陷。读入一个2048*2048的位图,等于在显存中保存一个2048*2048的贴图,不说是否所有显卡都支持这么大的贴图,单是每个Font字体类吃显存的胃口,就足以令人心惊肉跳。如果定义足够多的字体类,我想你的游戏的配置要求,在某些方面足以超过《DOOM3》了。 8 z7 n4 ~1 |" H  T
$ w& A# {1 q. W& u% d
        而且这并不是唯一的缺陷,文字大小相对于位图大小比例相差太大,导致浮点数的文字位置误差很大,你可以在一个文字旁边看到其他文字的影子。(虽然可以通过增加文字间距来解决。)还有点阵字体本身的缺陷,就是字形单一,不适合放大缩小,一些文字边缘的马赛克,足以熄灭任何玩家的投入感。 2 F; t+ c, H- F) t- l& g+ z/ u' C
4 f; x4 D! J$ \; I6 H
        似乎TTF是唯一的解决之道。 & X& ^: {4 X: S3 Z

1 t- _, _/ @3 H! m5 o2.基本知识
4 w* D$ q. [# _1 k9 S: U' D+ m9 x4 Z- r" F
(1)TTF字体。 / I' |- q3 s7 y) E0 d
7 p! W" s- s/ S, J' f3 C- ]
        TTF是一种矢量字库。我们经常可以听到矢量这个词,像是FLASH中的矢量图形,在100*100分辨率下制作的flash,就算它放大为全屏,显示出的画面也不会出现马赛克。所谓矢量,其实说白了就是用点和线来描述图形,这样,在图形需要放大的时候,只要把所有这个图形的点和线放大相应的倍数就可以了。而且,在网站上有很多的TTF字库可以下载,或者你可以去买一些专门的字库光盘。然后在你发行你精心制作的游戏时,可以顺便捎上这些后缀为.ttf的文件就行了。包括Quake这样的惊世之作,也都是用的TTF字库。   Y+ O; E: l  H0 q/ [

% @& ~6 g$ C: @/ k& K! i(2)FreeType2库
- z" C! }+ P$ ^( ^$ o8 @& u9 T& k9 j' @' ?- G5 n2 S! G  c( y
        在http://www.freetype.org,有一个FreeType的免费库,而且是OpenSource的。它目前有2个版本:1.0和2.0。其区别在于,1.0只能读取TTF格式的,而2.0支持更多的文件格式,在使用它之前请详细阅读所要遵循的Licence,以下是摘自FreeType2.0对字库的支持列表:
; ~8 |$ e' y2 u8 [" _: [8 |9 l8 j6 g$ C/ k/ L; F: X
        TrueType fonts (and collections) 8 j8 Z" r9 i7 j( E2 U/ Y* ?

  Z) _2 E" i3 {9 r        Type 1 fonts ' z% F- o; k5 ~1 d2 r# }  Q6 Q

0 k5 N) |1 J( z; ]5 m        CID-keyed Type 1 fonts 8 A, R; K( n* v5 P
) D" ]4 P. n/ H3 `& `+ l
        CFF fonts - G, J; g1 K5 _* `

$ N8 C& _& M$ r- K        OpenType fonts (both TrueType and CFF variants)
) `: R( O5 w+ r
' n+ y6 I* }0 L        SFNT-based bitmap fonts * R5 i$ N" {) A6 N- s

: ^1 ?( s, M9 V: q/ x        X11 PCF fonts
+ C' }8 ?" z, {5 ], E4 R0 o
9 y6 A, B, o( X6 l" V' R9 P% o. \( }        Windows FNT fonts 1 Q: S. @5 g$ R1 N8 q5 i( Z/ l0 {4 ~
* G% D  F5 f& I) Y
(3)“主体思想” 9 n, Y. y8 O& j5 Q1 n7 @$ A- g9 b3 M* L

- z* ?& i$ d' ~        请参照炎龙工作室的《游戏中汉字显示的实现与技巧》这篇文章,可惜使用的是Windows API,作者千里马肝,上网上搜一下吧。 % H# a- y5 ?  r9 F6 U! D3 M

4 ~! W" J; @! m, R' \, C        附带说一句,上面两条都是直接从这文章中剪切下来的,>_<  不要骂我啊,不知道算不算侵权呢。 ( }+ h8 m6 E9 p$ u' T

3 Q. h$ a( M; p* \7 z3.动手术---比你想象的要麻烦 7 ~0 ?* N, z  N9 ?
(1) ) C" @1 c$ G$ X: Q) z
        首先要告诉字体类,我们下一次渲染需要哪些字。以便字体类可以在需要的时候释放不使用的字体。 6 B; E9 |7 _" T, q4 R" ?

) {4 Y3 e* w5 M1 N3 @2 Y        在Font类中~ $ w) p. G% S2 M: ^

3 y; S) e' R( b, n- u        a.增加数据 bool mUsing[OGRE_NUM_GLYPHS]; 用来标记文字是否使用。
7 Y  i% Q6 v" }/ Y" r; K9 O5 Z
  R- b- |- H, M0 I# Q& @        b.增加函数
) x" S7 _/ [8 I- V, |' I9 N0 s) D( H! r3 p
                inline void setUsing(std::vector<unsigned long>& caption)7 I1 M% X/ k( M0 Z* w2 i* Q

+ u5 s$ Y* H5 M7 I1 V                {  R8 u; }+ D" m+ E

. p) o* [3 k% k                        memset(this->mUsing,0,sizeof(this->mUsing));# d! B% \  C* y3 {, x" F% ^

1 s) @! O# d" h5 t9 N) C                        std::vector<unsigned long>::iterator it;
. V- n" W, w* ]2 I5 C7 @; F" T
4 L4 F% r/ [$ c+ L8 K; A7 l  b/ C4 N8 [                        for(it=caption.begin();it!=caption.end();++it)7 D6 o, A4 F9 ^7 }

6 K3 d0 a4 Y4 e" F% u" G; m                        {
* f8 a& o: V" e4 H9 _! f/ w5 k6 {. {) k5 O; C  y3 Y
                                if(OGRE_GLYPH_INDEX(*it)<OGRE_NUM_GLYPHS)
9 k  Y' C. {0 o) Q. s0 O; R  z- L1 ^+ p
                                this->mUsing[OGRE_GLYPH_INDEX(*it)]=1;//标记文字为使用
& F  K8 r% @% F/ u6 n7 x1 \( _: F) e$ ~, E  }) I- p9 J
                        }0 ~$ O3 n- o6 `, h1 T) U1 z

1 L5 J4 }" F8 ^+ B3 y# n                }
1 X9 I3 R1 M9 {- k
: d8 E9 g' w5 }' F) L/ s4 K% W7 y        并在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。 ) M& |/ E1 g* l+ }. Z0 r  L. ^
(2)
7 s8 b) i" s- r* {
, |* i$ [; G" }1 ~  L2 m        然后是修改void Font::createTextureFromFont(void);# V5 \7 T. s3 ?- O, W) ?. N
0 N8 q) @4 H% Q' Y
        Font类是通过void Font::createTextureFromFont(void)来把通过FreeType2分析好的英文字画在一个2^n*2^n的贴图上,然后再保存英文字的位置。 7 m, C% M/ n' J5 U# ~* y9 h1 r* i

: f! P0 \- t7 l3 Q6 j2 A        我们需要修改的是:
* R' D! O9 O3 y9 q# R# k7 i/ X' r8 U* E( d& s: x
        a.从函数中分离并保存画字的FreeType2和辅助变量。我们通过一个类来保存和处理这些变量。
$ F8 s0 Z: q  |! }+ X% L+ j/ Q3 l
. w% a& T' l8 b+ s1 `0 [        class TTFMsg+ `: k/ }0 e4 v
0 A( m- I( D2 D
                {
9 w- y9 m6 v2 _5 K0 l7 ]/ ~+ H
$ E8 V4 f5 R' B( {: t3 n                        class Max//类中类,用来保存几个"最大",2 H! s, T+ }& |: I

  d5 Z/ t- ^; ?/ y  w                        {+ X% E( k  L2 R' g! {% m

+ H5 W7 U# x: j                                int nothing;//这个是用来占位的,没意义,反正没他就运行出错,可能和数据对齐有关吧。
4 S. s3 a0 l. x% |, g) g! {2 z( x9 s: U
                        public:
; h" f3 }; [; F7 M/ r  r) t                                int height;//文字最大高度
- l1 D: Y9 F) p. W* q) t* n; D                                int width;//最大宽度
) t0 \2 h- }- I+ g                                int bear;//最大空隙? 5 v4 U" S/ t- K. `* g3 j3 c8 G" X
                        };
  O# u$ M# Y8 ?: l4 |                public:
7 g5 ~  C! @* t                        FT_Library ftLibrary;//FreeType2用 4 q# k0 A; ]3 j; U7 x( K
                        FT_Face face;//FreeType2接口? . z+ {, N8 }2 t5 p! ~
                        uint char_spacer;//文字空隙
8 g0 C4 m& `6 I- B% J                        SDDataChunk ttfchunk;//数据块,用来保存ttf信息 . a( ^" q0 e. B: o
                        FT_F26Dot6 ftSize;//FreeType2字体大小
* |: J: t+ ~# H; v8 R                        std::pair<uint,uint> point;//在位图上画字的点 7 A4 h4 E4 }/ T6 X
                        SDDataChunk imgchunk;//数据块,用来保存位图信息 3 _+ Z7 ~! d7 Y0 \( l0 ]
                        bool dirty;//标记,看是否需要更新贴图
% u5 R* t3 s8 k8 h                        Max max;//几个最大 1 x$ e$ I7 k9 z& i2 y- G
: f1 ~& ~, d0 e; N$ U
                        inline bool init(Font*  font) //这个是初始化函数在void Font::createTextureFromFont(void);中调用.! D! @2 o; O6 A
- c3 h+ ~2 J2 @, O
                        {      
9 v. E: I$ a. w* i$ o/ |& s/ w5 q2 {4 H
                                //以下都是初始化,大部分都是从void Font::createTextureFromFont(void);移植过来的 : Q0 Q& r3 ~6 h% d, @

4 X9 b* V2 w8 n5 u( n3 h! ^                                dirty=false;. X/ b" W$ F, i& ]& `

/ J, N: J" h7 C9 _                                if( FT_Init_FreeType( &ftLibrary ) )% F( Y: q; x: N; u) n

) z; a: K# N- b5 R4 f4 Y- O/ A                                  Except( Exception::ERR_INTERNAL_ERROR, "Could not init FreeType library!",
& m, z! H' U: g  I' ^3 O& g+ |
' e1 [) ^5 s: R& W                                "Font::Font");# h4 L; j: o- I5 Q

) ^2 T1 U9 l( H6 W! g4 U# G! S2 G                5 \4 W$ c8 Y# }. |
+ D) k/ b8 S3 t3 d) ^2 }0 s; y) n
                                char_spacer= 5;
/ F* ~4 O7 B' }& ]) A( g3 S
; p4 i: Z) ~; I! ?                                FontManager::getSingleton()._findResourceData(font->mSource,ttfchunk);
2 q- m& f5 r, X% w* D
" _4 \. C* Q0 Q! }) w( Z% O, \8 ]7 ~                                if( FT_New_Memory_Face( ftLibrary, ttfchunk.getPtr(), (FT_Long)ttfchunk.getSize() , 0, &face ) )- r+ H* {' E, y7 T

' j: W- J: Q& k1 ^& A1 `. n                                         Except( Exception::ERR_INTERNAL_ERROR,
& y/ G& k+ @7 Q# d& u( _, d, d/ Y% A9 z8 b' u" o
                                        "Could not open font face!", "Font::createTextureFromFont" );% G! N2 |) J% r- B+ j/ I

: N1 C& I; V. f2 R+ S' C, O. q9 x                                ftSize = (FT_F26Dot6)(font->mTtfSize * (1 << 6));! F: o6 a0 p/ c2 [
, E; D9 m5 M7 l# F% I
                                if( FT_Set_Char_Size( face, ftSize, 0, font->mTtfResolution, 0 ) )+ t$ ?" f: S6 \8 I3 q& D, G
1 j8 L. G6 x* B0 }" |% v6 X5 O" A
                                        Except( Exception::ERR_INTERNAL_ERROR,
; x1 L, k7 W3 H; F& L
! q% B& k3 J2 b                                        "Could not set char size!", "Font::createTextureFromFont" );
2 v7 B9 l6 G! v3 X( Y3 j3 \3 [* S, f) Y
    Z" w. t. m2 ~0 ]/ E% K$ t' A" Z3 m
1 R2 w# o% x# Y/ E5 h" Z! R. d/ v
                                return true;( l: F& s) o) ~, F% m$ I; E0 Y8 Y

- l2 I( z8 C- k+ c                        }  X) |0 Y) E- f( N2 i: ?
% I" i; W4 q) P) _8 W% P
                        inline bool done()  w& P2 p$ e7 t1 f' u  |
  b- q8 C  u' X/ E# i4 G1 z; G- K
                        {0 G6 N/ D2 ~5 V5 L4 \8 T: B2 s
2 a6 ~) u. Q" A0 {3 U  v& n
                                //在Font的解构函数中调用的,本来应该调用下面两个函数,但是不知道为什么一调用就出错,不用倒没事。 5 F& |3 Q, h' y# C, H; M
/ c0 E$ z# t4 N
                                //FT_Done_Face(face);+ b2 [9 L- v: E5 L  R( r# b

; _8 d5 u, m2 p% Q4 V, g$ c                                //FT_Done_FreeType(ftLibrary);
: a# s0 ?" V" I( }# H! d" V$ u2 @3 g# F) c
                                return true;
' e( P0 y( }# x+ D- W# l2 P+ I, o! f" A
                        }
( k4 p( C) w' ~4 G1 h+ y
+ ]9 _1 n, O7 D; K' K                        inline bool getRect(Image::Rect & rect)//这个函数以后用的,是用来找到可以画字的贴图的空的位置
; Q8 f$ C6 M0 i
6 ^' u# v: y5 K0 n                        {
& p. t+ Z0 D2 S0 z3 ^9 s' t5 q0 E/ _/ x5 g
                                if(511<point.second+max.height+char_spacer)0 g+ g; a# H5 T

' t) M. R. [# F/ A/ j6 l: R& j                                {( q9 S+ y5 h0 S, c1 X

- B( S7 _% {- X. P/ R& V- f! _                                        rect.right=rect.top=rect.left=rect.bottom=-1;
3 w- S  e; Z$ ]7 y5 d  F1 h) K
0 @3 k, Y, g2 p9 Y+ T) C                                        return false;
. a# o6 D9 J% E7 m1 G0 G7 c; v) b& J& |$ W' \% i9 A
                                }8 D$ c* i7 \/ T2 c5 B7 L) j

. J7 Z: y3 c- W) V4 H0 `6 R                                if(511<point.first+max.width+char_spacer); [7 \# ^9 d/ l$ q, r3 S. K0 r4 q. V

; C2 @  r/ d+ t0 S6 I% j                                {3 x. L6 e. `: Q) k; a/ D) }
7 A* I7 |/ m  \4 T/ c, X
                                       
( t* q% j3 T" H4 B/ z7 m* @+ E$ L' v4 Z& E# r
                                        point.second+=max.width+char_spacer;
. ~1 Y/ y  l* o7 i) z
9 g1 K5 U* C9 Z% G                                        point.first=0;
8 v+ x7 k' C; F+ ]& i0 m" a# V  N  ?) ~
                                        if(511<point.second+max.height+char_spacer)* _$ Q1 f3 i' b! q9 k8 W7 T

  J5 k; K- o7 W! a                                        {
* _+ g3 o2 x- D& r* ^' y3 n- S4 j, K# u& O
                                        5 O  q4 ^- D$ }* `
" w6 l& o$ Q# [  a5 g& j: X
                                                rect.right=rect.top=rect.left=rect.bottom=-1;
, @7 }7 Z, b% A( Z. c6 V5 z2 k9 t8 D0 i
                                                return false;
4 o  W8 P2 a$ }: D) r) G$ ?
7 |: y9 I# p9 r( m* O% q2 h                                        }  e* l9 H3 q# K9 x5 S. t3 J
2 Z2 x( d2 P' \) b3 C  A- n
                                }
5 T* _, [4 U- H2 W/ r4 W: l% U1 t1 q6 |9 S
                                rect.left=point.first;
' b0 u3 j2 c  w& M/ x  H: q4 N" U2 X/ M- L7 S! w" K
                                rect.top=point.second;( N. J# {! Q' U3 M
' _, o( ~8 f! u) R8 c
                                rect.bottom=max.height;
4 T+ G$ z( f$ |/ }. c4 `3 U; z# b
* @. R' [4 y  S3 J                                rect.right=max.width;
9 Z! c2 J1 q) A4 [/ I4 q. B- j
! t4 L7 u% h6 b4 [; V+ l' F$ ?                                point.first+=max.width+char_spacer;( J. N  B, ~, I

9 Z/ R* X; J* J" q                                return true;+ r" `# I' f. K6 I
7 ?6 O3 L5 B3 W: \5 ?5 H) u. a
                        }) p& p$ o6 g' {+ C

, ]  q0 ^7 [; U+ \' x* W' r                };* H  \" F  m$ q3 O3 y9 S) `

0 Q" Q& {/ o2 ~$ \        上面的类定义在Font类中,在Font中增加 TTFMsg * mTTFMsg 数据,并在构造函数中 mTTFMsg=new TTFMsg;2 w+ |. o7 j5 r, y" f
! V7 q( C9 ~: l) ?1 K7 W
        ( H+ v7 A  y+ G/ }# n$ b) A
, A% \' q- Y6 s# V$ X- p
        正是修改void Font::createTextureFromFont(void);函数,主要几点,首先是分离出很多变量和构造到TTFMsg类中了,然后是贴图从2^n*2^n变成固定的512*512,为什么要这个数字呢,因为256太小(废话了)。能保证512*512大小的文本区不会出现不够画字的情况(所有英文+符号+没有重复的汉字),这个安全区域基本上是够用的。(什么,你要画满屏幕的汉字?哪你自己看着改吧。)还有一个重要功能是,要找100个汉字,找出最高和最宽和最大空隙作参考。修改完成这个样子了~8 B9 s; M! p( f+ e

/ q. H! f3 D# _1 J' Y/ }    void Font::createTextureFromFont(void)8 p7 K9 ]% g7 q! i
& y& [+ n& g" |( E' w
    {6 w1 O2 }8 j* x0 R
1 w- F8 j: v5 \4 y9 b! v2 [
        mTTFMsg->init(this);//初始化FreeType2
3 E1 D) l* U2 I. _6 b
$ b. x! E5 T# r! D' B0 V% T4 Y- G        uint i, l, m, n;
7 u+ S: C- y& B& `+ i, }% Y, u6 R. l* O0 L3 i
        int j, k;0 V/ W% H2 o3 _8 c* E3 p( e
3 n: x( D3 S& F
  1 w2 k' {( o, J  O# ?/ l! w
, J" U' w/ B/ p8 \  O" A% H2 E
      
4 b1 h2 e) P5 F& Y. C$ n7 X% a" p; A3 W
        FILE *fo_def = stdout;//啥意思?我看不明白 6 V. I4 V8 {( Y# y/ C' b! f2 R2 q
: f" j4 r+ o+ Z4 c, M
  . Y! q' f* X. Q  Z, ]
: \# M# Y. S8 P! E
        int max_height = 0, max_width = 0, max_bear = 0;
, R* }7 o5 C) g) L% z. u' K
5 m  E  C$ ^! u' m. c  / K. \! H1 W! R8 m3 G
& `9 f- G. N4 }& B; i4 p  Z
        uint startGlyph = 33;) [) E, q6 D# X# L# d* E
3 t1 R6 L/ r9 z, c$ @+ k
        uint endGlyph = 167;
0 H' X7 {' [: [) e& L; v
9 C) I5 r+ p( A+ i9 q  ! U8 w. B. c! k$ Z2 H- \5 Z) o3 d
) ?2 B( `1 \  j. S0 r) f
        // 找英文的找出最高和最宽和最大空隙
0 T" ~6 x$ s3 E! H: T9 K0 ?, q. g* Y' J' P5 F9 n$ Y
        // Calculate maximum width, height and bearing
, L8 v- n! o$ \) b8 ]( C0 {
: _" T" {5 I* s: x8 j6 ]1 s" d        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )
) p* d3 I/ ?8 w0 J
: M5 Z" n3 {& J  ]        {4 }; ~* F! V" N' o

* u# [. N4 B3 G% W" B2 L1 j            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );
$ _. h4 o1 Q. t
+ x% \2 `, k# y, P4 a$ D3 V9 O            //以后的 <<6和>>6都是FreeType2中的数据和我们使用的数据的转换 $ ~" ?# E- p4 ]/ ~% @- B# ]3 H

" d' @' T; @4 ]" L8 A0 g            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )
; Z0 L5 j- S5 w/ p' I! g. ]- d  i. \4 F- c
                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );) X, g+ w/ T8 z/ Z( ~/ V, {
4 R) j* {" h4 @4 S4 |+ R: H
            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )
/ a2 s/ `9 }' m% P$ F2 H/ G+ F2 Y$ t* z8 U: M& S" N) v; z
                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;
% F! P9 i; D9 Y1 C  V: x8 p+ T  ~" K( ~, I% {2 [! u) w
  
0 R- x7 N' x5 a- ]
  ^+ U$ ]. s! o2 j* I            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)
7 q& R2 S6 N8 p! B$ e. ]
) \8 {, }  g" ~2 V1 o' ?9 [! i1 l                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
+ P% o4 e+ L4 C' ~9 \6 V; `5 [  y) S, [- q  a; z; ~
        }
6 }1 l1 D$ v) p1 v" w
* Q: v/ W6 G* B, i: ~( I  
5 s) l* @/ R: _) ^
, _5 |0 x8 l- C6 u+ `3 T  $ ^4 [8 `" y$ _3 D

2 k) M' E' ]. l$ h& z' K        //下面的for是找100个汉字,找出最高和最宽和最大空隙作参考。姑且认为最的汉字就在这一百个里了。 ; ~6 w, X* H. j/ I9 h, j8 \. M+ T
5 N# X7 C7 S0 _
        for( i = 20643, l = 0, m = 0, n = 0; i < 20743; i++ )+ `& v% @$ B) J' {0 Z
% Z- s$ P5 q/ I" y
        {
1 f6 j1 j1 E. o# u' }! `3 X/ ]# C5 d+ k2 \
            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );' b0 N9 [& x% v7 E6 Z

, `+ p! f, c2 B) @- w  
5 ]1 w0 Y0 {  H1 k# v
/ Y" |9 u) Q4 i6 O; Q            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )" o8 V5 `  ~- [3 G, G5 ~6 K. k: ]/ s) }
$ @( D; ^8 i- e: X  J! t& b0 W3 B
                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );
) T1 r) }$ z4 i. S7 i4 `) }' F) ?2 H0 t
            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )0 c1 R+ e1 i$ y9 p
: d9 r! w7 A( h+ I. b  U, B
                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;
' J, V( N( `  x# f* b* b5 e; ~. I8 U2 ?7 ]1 F
  - {7 U1 h. }* C; D
6 [: X2 g' T- y0 C& _1 ]
            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)6 _: T) w- m6 n4 R+ a+ F# H

+ G1 v" h/ ^4 H# K) b! f7 O- W7 q                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
: r  }( Q0 [7 ?
! L3 Z, l  e" K1 F4 K  5 Y" `; ^# w' p% G) x4 C
7 r1 `0 c5 p3 B- u' D
                        : I: v# x7 |* U' i1 G# ?

3 e0 a1 N# }6 j; n            if( (mTTFMsg->face->glyph->advance.x ) + ( mTTFMsg->face->glyph->metrics.horiBearingX ) > mTTFMsg->max.width)5 h- Z, w# T5 M2 B
9 R; U) O; D# k( ]
                mTTFMsg->max.width = (mTTFMsg->face->glyph->advance.x  ) + ( mTTFMsg->face->glyph->metrics.horiBearingX );
; H6 M. Q  B: D% C) _
& L7 k+ t. C, d8 y6 {. b        }/ v, Z( b+ }0 H
/ M( j- d' e# D" t
  
  J- o; @9 L; M2 x$ {9 Y1 H: m2 U2 m/ l
                //下面几行行不需要了 我们要512*512! r7 J! l5 A$ ^- U; G0 y4 x
  n$ \; U  {" a! H
                size_t tex_side=512;//就是这个了 5127 g# c+ z! X0 g1 P3 k7 H/ _
* K+ i7 m4 q0 a3 ^
        //定义数据宽度 因为是32位的位图 四个char为一个像素,为什么要位这么大呢,难道不能用8位的么,我尝试着改来着,不过改了之后就不透明了。望高手看看能不能改。 ' \6 T% `6 {* A( p! B

/ G5 c1 f% G% b/ N5 ]                size_t data_width = tex_side * 4;
+ o% q4 A+ _; ^# e
* C+ M8 y( D' e. Q  
/ H( r3 X3 a) C$ @8 P! X9 s, g- B: H7 U
                LogManager::getSingleton().logMessage("Font " + mName + "using texture size " +
. j" w3 e( p, t$ J7 d2 V* }) f
4 K9 L* v. G  H# g6 D                        StringConverter::toString(tex_side) + "x" + StringConverter::toString(tex_side));
2 l6 ]3 R  ?2 j; ~
3 K* U- [! i, A5 }0 a  X7 U  
( ^; R9 J0 n- U* J8 y$ C
+ x2 L1 q3 c- k: E        uchar* imageData = new uchar[tex_side * tex_side * 4];//设置一个空间用来保存位图 % S) b! a# A5 R# S+ h+ }1 e& \

% N+ V* n' g1 f                // Reset content
6 f" u! M! [7 z7 `& ?+ a3 _& I5 u
' |6 d6 U0 m5 r; q$ W: L: F# o: ^                memset(imageData, 0, tex_side * tex_side * 4);//清零 4 k+ G+ I( Y! X2 Z' Y
# K' h* e+ W+ V
  
! x! m& [' y* [0 F3 v0 w' ^% h% `+ J! T: Y3 x
        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )//遍历每个字,
( F3 I8 J9 b! y: H
6 x3 v8 U4 `7 Z- e        {: X. F& j! Q) D

  ]: m1 j( l2 ]                        $ S; |+ G: \7 t3 P6 @

5 D# Z, B+ d6 M            FT_Error ftResult;
8 [4 ~  \0 y7 s" W
: }' ?$ w5 F: C7 \5 ]  
' W0 P( e7 Y* d6 ^5 I+ o- `( j7 c" `: [, `& ]8 A/ i! N0 w* }( g
            // Load & render glyph
* R4 }; ]; a2 Y' c. a: g$ C/ Q8 V  y7 D" A/ a9 t! [- c
            ftResult = FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );//读取字体
8 N- I( _2 d# X& n6 I# E( l& i' L) e8 I9 F& m6 Z! x
            if (ftResult)
4 x0 g! A! b* n6 E
2 W  q! [1 X( [, h( a" D            {3 @" F3 D6 R; E; _1 t+ z7 e

5 m, i' y* d1 }4 u2 ]                // problem loading this glyph, continue " H$ W  e* H# {9 J
/ f; q% t8 ]1 X
                LogManager::getSingleton().logMessage("Info: cannot load character " +
! u0 W) Q( }* w1 [9 L7 o; F, J: s0 v9 q- L
                    StringConverter::toString(i) + " in font " + mName);* S6 a5 u+ b3 Z) y2 `

: b7 A$ V( G8 t5 F* u; ?0 I4 t                continue;//如果错误跳过 ) [" h6 f  w0 d5 b0 w2 v% l9 T
0 t7 ]. t+ Z: V4 Q7 N8 z
            }
# [5 z* f: ~6 t2 j
- q4 `" `, F! `  : G2 N8 U! l  f: Y7 p* M

$ \3 \, n5 M/ g, s8 B                        // 应该是字宽
5 Z) o/ `: ^, l* v! i
" u( A+ O; B" A0 B7 r" N3 A: b2 @                        FT_Int advance = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
9 `& u7 r2 {: c6 c0 c+ T7 A3 z# T7 M
                        
" y) D$ ~. m4 r
8 ~6 K8 y& ^! [& Z: H4 C+ ]1 a                        // 得到FreeType2的位图 2 H! m% ]. v+ B6 A4 j+ Y# p# k

: J3 {: I6 Q. ^8 i# T            unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;3 p  q8 g6 P& `5 o# o: W7 R
/ Q, [' X! H) r4 w1 W* z+ M
  
4 t  `7 m! [; d
. D1 y, X" l/ {" Q5 q            if (!buffer)
. S/ T' g5 {: m% G1 \
' P/ n( f$ }1 H0 [; K' p+ k            {  m4 z7 e: J4 C

& L1 `. `( r0 x                // Yuck, FT didn't detect this but generated a null pointer!
$ x1 l3 I$ u! r( g" A" ~3 ~! k, R1 s- O2 m. ?9 l
                LogManager::getSingleton().logMessage("Info: Freetype returned null for character " +
1 s, m4 u& X. ~+ u* ?# g6 D1 k
- j8 w- j! E& l5 g! j                    StringConverter::toString(i) + " in font " + mName);
7 W. h* ?  ^7 M
. ?0 {) j; {7 \2 |5 }$ |                continue;//如果得不到跳过 8 R7 b6 i2 t! z$ q, J% R0 u! H

8 \: i7 Z8 T% f6 W8 K            }
0 a- W: p: D+ ]
: ?; l# l4 F& H' \7 Q  * _! i: H$ i! B2 k" {+ D; q4 ?
) t. A8 \% O% [5 ?  W
                        // 得到y的空隙 (最大空-空-本字空)就是说空出这些字底部就平了
9 K' z6 Z3 j# _1 C9 J
$ y: T# H) K9 K- s# f7 c( _7 W            int y_bearnig = ( max_bear >> 6 ) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );
# M' d" V/ ^9 u6 V% P1 }: Y, p8 f/ S
                        5 U5 s( Y6 H; n! W4 \( B+ j

# ~5 n6 y9 N1 E* C" E2 b. s  g! s            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )
" l; B- G( k9 m% p; X5 f/ G! H1 p3 l
            {+ g+ {: V% j9 [* A

4 w- i! R* F* m! S                                int row = j + m + y_bearnig;//相对行+本字在位图的总行+空隙 % _0 e9 O% X% Q; a1 h! i* c$ a- u, j

- p+ F) t2 q! ^. M: a                int col = l;//列
6 v, e% g5 Q& N, X# o% x8 B& g6 E, x: s& M: _& j
                uchar* pDest = &imageData[(row * data_width) + l * 4];//找起点   
  D  [3 m, B& F. h" U: s3 j5 W; i* i* S( F
                for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//画图 0 u! {7 v8 n2 P
4 G4 q* U. H7 F$ q
                {1 j+ B' ^% Y9 W% T

$ _6 L& t3 E5 C& H' _7 H# O. {  ?% a                    if (mAntialiasColour)//看不大懂,难道是灰色字体? ! J" q. {& e0 ?

5 T$ I, g$ v  S. T5 c) K/ u3 t                    {3 a( A" n8 C* p, }( s; p5 l

2 e- [" S# I% J9 S' s: U                        // Use the same greyscale pixel for all components RGBA
0 y9 x/ }' \  y* Q+ q7 m& i9 h* D% j7 h! B- u6 a  j
                        *pDest++= *buffer;5 Y. }# j% ?4 w

. p9 S; u' ~, O3 [" H- b                            *pDest++= *buffer;( I0 I+ w) t. S& h' O
' }1 A3 `, R9 C1 Q- I' A
                            *pDest++= *buffer;* S2 s/ e( |3 p6 |& l

! z  e  t. [/ I                    }. K) C5 S, m/ ^$ z$ ]4 B! t
5 E% r1 [# M5 ^) @+ R" F
                    else
; c4 L6 M3 \; N6 f$ c5 I% A! P( m! _) B2 Z
                    {% c3 s- [% b4 _: j) S! R$ U
- F- ^7 w6 e) r& v
                        // Clamp colour to full white or off ) l( `6 ^& r  d" }. w/ [

; q: W3 I! L% u                        if (*buffer > 0)7 \; w9 s" W4 L4 ~  @( A+ ^% a) v

6 B3 `; L! J; s, Y# x  S0 [& U                        {) O/ U5 S  v* F

( r8 }2 A% a0 Z3 x- B9 a7 D                            *pDest++= 0xFF;
4 U' d- v  K/ }1 U$ k& I" G; C4 m6 x+ y$ b
                            *pDest++= 0xFF;
5 z" R+ }3 O1 T) f! g& n3 Q( u* F6 \5 e' F' r* V
                            *pDest++= 0xFF;
8 e5 Z  t9 h5 s0 ?( s1 [
$ z+ J3 ?4 t/ V( S9 y                        }0 i- U, U- P" r( K* `& ~- l! \1 U( U

( P1 E8 e% [+ |- E) B: @                        else ) g1 {: I0 x: K# h, N0 w
- w, @; T2 P* M7 U0 Q" g! E
                        {
& E: J% k, X4 ]+ V4 |6 [
8 u" x8 S5 f* u; s                            *pDest++= 0;
. m- W  K9 S+ h0 N+ F) o! r6 Q+ F# o; a3 {1 S9 G; \5 u
                            *pDest++= 0;
) C( a6 ~( D$ ?; C+ z$ W
1 ?9 `$ D1 l) T; ]. q& C7 u                            *pDest++= 0;7 A" C/ H5 L& S/ @

  a6 \5 W: p9 A9 M# m                        }! e1 U* Q# [+ e3 j: y* `. l

1 g/ Q7 }- i. N1 ]9 Y                    }
; o! E  j$ `3 h: X1 o6 I/ Z
. B8 g+ v7 i: c/ E2 _                    // Always use the greyscale value for alpha
! C* x% O! E. D5 _$ j" p, x
8 m# }# ]+ }! Z3 u( x                                       
3 @4 ^: d9 @9 H9 X* m
; G$ e7 R& m* I6 m1 r$ m                    *pDest++= *buffer++;//alpha! 我是一点不了解了为什么是这个? 0 K$ Z9 n) Y. z3 q" e. {

) L- J/ G2 c: X                }
" i' z* S  b) \. k- o+ }
# B  e5 C& w1 r; v. Z! S            }
) ^0 B4 H- R( `- b% I+ l) N( D" o2 g$ ?0 ~1 z
  7 D3 W# \) g; [1 |% I& v$ }

5 N7 p" u9 o8 K- c1 S; i; ?8 K            this->setGlyphTexCoords( i, , W5 K  R, e4 N! r1 L( i, n+ r: r
9 D  A) H( r; I: U
                (Real)l / (Real)tex_side,  // u1
/ J. e4 z4 x+ H8 W
) L  O6 J! w1 H% _. r$ u                (Real)m / (Real)tex_side,  // v1- h4 ?6 ?" @; ?0 R( T9 _7 b2 b
/ k" Y7 I9 k; ]% p9 z) E
                (Real)( l + ( mTTFMsg->face->glyph->advance.x >> 6 ) ) / (Real)tex_side, // u27 ~/ R2 W. H- W* [3 Y

( `/ A% ^* e0 R                (Real)( m + ( max_height >> 6 ) ) / (Real)tex_side // v26 H/ M4 T6 T  j- [0 g( ~/ o4 V/ d
% J7 U3 b& T# {* B5 D$ N
                );//设置坐标
0 a1 q$ }* p9 h; c* X7 n3 U
; V6 R1 y* P% U  
. [, z' f3 i4 @3 {
4 K: v% T2 `, M* d6 T( e' ~# |            // Advance a column
; E! D& s& I8 f, F5 ~1 `/ ^3 Q9 q* `' O" @( k* {
            l += (advance + mTTFMsg->char_spacer);. X5 j# O. L' X0 O' Y

2 S2 x6 O; R2 x6 @$ e- k+ g                        //l+= 本字宽+字空 2 Y0 N. E6 X" i3 a0 a. ]
  m* |1 f" v0 z4 O6 F  U
  
5 w) R, Z0 S1 L+ F, c5 ]( U5 e
6 T) I6 u1 x5 X# L& h: m            // If at end of row
- a) y8 l/ H" b: ^7 d- S
6 Y0 W( T- |7 j9 s                        //如果到头容不下一个字 ) u& y" H7 x/ y& l1 a4 W

5 B& g4 c: t. V4 {            if( tex_side - 1 < l + ( advance ) )
' l5 b3 ?: q. q/ Y4 \9 Z9 G" Y% p7 n
            {" W5 d9 f' V2 r' u

1 z" ]# y/ \2 s2 |" F1 A4 M                m += ( max_height >> 6 ) + mTTFMsg->char_spacer;+ Q: ]0 Q- D5 \# v* H

) {7 F: g; g& q3 k* `                l = n = 0;1 e6 A6 D7 }9 Z3 K) `1 u
- r2 Q& N8 ^4 q; E; w/ v9 C+ x
            }
8 t: |: b1 S: H4 X$ F' A
. _. k* X2 L+ Z1 v0 p3 t0 e1 w/ F1 U5 J  
0 [/ N! O3 t7 L; t9 R. r: ~) _% d5 V, S$ t3 Z3 ~; j- k
        }$ _, ]/ t% x) b$ j9 F+ j# P

8 {2 o0 d% t0 O+ [% Z" z; B                // 把信息存到我们的mTTFMsg中 >_<; r9 m* g& t8 T/ X8 O5 v  y

/ f" {2 g) q! o; L                if(l)
6 E/ t0 P. [3 Y; c
, K- n$ `0 H( t" p1 {                        mTTFMsg->point.second = m + ( max_height >> 6 ) + mTTFMsg->char_spacer;
* H1 M! u$ N) X6 ~, |
! R. h; A9 t: x* b% q+ m                else
2 R, z9 Y; C' p* P# }/ T! [3 ]- C$ r+ P" l
                        mTTFMsg->point.second = m;4 F! y/ Z0 r; J

$ \7 n8 w5 o2 J* ?  h; C  + _8 j, G* }4 b% B( w

+ j8 _; n5 }* L8 O                mTTFMsg->point.first = 0;//另起一行
+ {3 S0 N1 q: S; a: k3 q- j! K$ Z% T% A$ Y& h  k' ]
  
+ r0 p$ ]9 U4 O, _+ ?. y, M% A' D  l' }* r4 ]. q
                //下面是保存几个最大。 & Q/ C/ v) S* M1 r

- K9 f+ f. D$ G: P$ D                mTTFMsg->max.height = max_height >> 6;
3 d- a. Y; T- J, W+ x. O( M
2 i, H8 P5 W2 Z# k                mTTFMsg->max.bear=max_bear >> 6;
4 x; Q- ?- }+ g' @; `/ I7 G6 ^3 J- W- T/ C
                mTTFMsg->max.width=max_width;- f; Z( s) w; @; l1 W

" C. e/ I/ X, c) ?( Z, J$ l  " f  w5 F0 Z0 K: }
$ v' ~$ T( \% h5 w
                mTTFMsg->imgchunk.allocate( tex_side * tex_side * 4,imageData);
, V+ T' E1 k* [+ W7 O
9 H9 e6 E4 w6 h5 i+ ]" B               
5 f2 L3 _& r: j( r# y8 c5 K8 a- R0 p- P  K. C
                //不知道为什么要设置img这个中间变量,似乎可以直接从chunk创建贴图 + R! W" |5 |" {9 ?; J$ J8 C

- V" O7 n2 Y+ W  I0 t9 i: H+ X) s        //--Image img; + c( x' ]# J/ T7 o# U6 \

- Q) ]) F/ w5 J7 _- [! @: t                //img.loadRawData( imgchunk, tex_side, tex_side, PF_A8R8G8B8 );2 _$ [; ?1 ]' _, N& ~# Y: V8 X1 R
& |: v, p+ m8 S
  4 ^% A( N* w: s" P$ U

: t# z$ Y% {& @! l                //贴图名 4 ?& O  l3 h& x( x8 z/ [  p- \

4 X5 ]% p* G  a# c+ L0 w* Q# O) A        String texName = mName + "Texture";
6 A1 `  y/ n5 p! C! L; ^4 d2 m) O
! [& d, ~4 ^% L) i                // Load texture with no mipmaps
/ K6 o; q  n) n. O0 e4 |$ n. J) X' X$ R- V+ L
        // 把从img创建位图改成直接从chunk创建贴图 8 x. B( Y' S7 J) ?1 q
9 Z, g. H0 g/ n3 l. g
                //TextureManager::getSingleton().loadImage( texName , img, TEX_TYPE_2D, 0  );' v& x3 j) Q# ^/ U6 s( }; E  |
  O0 C/ U7 c  E' x
                TextureManager::getSingleton().loadRawData ( texName , mTTFMsg->imgchunk,tex_side, tex_side,PF_A8R8G8B8, TEX_TYPE_2D, 0  );
; [8 b$ c& R3 X; i0 J4 \3 k% {8 L. J! ^& b# @
        TextureUnitState* t = mpMaterial->getTechnique(0)->getPass(0)->createTextureUnitState( texName );6 A) G+ `& m) z1 Y
8 I) [/ c& n* Z* ~- E
                // Allow min/mag filter, but no mip ! P  j: d! Z+ r

  C9 `7 a3 h" j2 l& K3 Y) X7 Q' h                t->setTextureFiltering(FO_LINEAR, FO_LINEAR, FO_NONE);2 w  y2 o5 b' k$ G+ p( _7 z

$ S( `( w) P5 K8 S7 A9 [! g5 e        // SDDatachunk will delete imageData
7 a9 \/ {3 e3 {7 I" j" ~( R5 K! ~
        ; U& I9 I9 ]* N  G3 y
- w% W5 o9 m6 _: w/ a8 r  M. X
    }
" b) r4 e8 C. ?) v3 b& o4 @2 L
- V' X, X& F; q        你应该对照一下以前的函数,改了很多的。 . x9 m: @: Z8 E/ H9 g4 G7 A1 P

. g3 q( c7 I) C- M  : u3 V* z" v1 G( n7 l3 i9 ]$ A5 C

6 }$ @' d0 A1 \% E2 s8 V$ t- L  
7 D% d# c) D( A" T& v8 U
/ e' P' m: }) @7 z+ l" h(3)
- w( \% M" n7 ]( U5 l( V! ^0 |6 L  r
, K1 j9 F0 a# p! f7 h( J' _; R# C        然后最重要的是动态的申请和画字。 + e8 z9 I2 |* z+ ~
1 J: i+ a! z3 s' Z
        首先最重要的是我们要一个方法得到汉字的unicode码,我们用到了unicodeMap数组,提供了区位码到unicode码的转换工作,等一下提供这个表给你,好不容易从网上找到的阿,可惜这个表没有中文标点的对应,如果希望支持中文标点,就要努力找到unicode码并加进这个表了。这个表是这样的 char c[3]="邸";unicodeMap[94*(c[0]-0xa0-1)+c[1]-0xa0-1];就得到邸的unicode码,不知道为什么没有5165~5169的unicode码,是轮空么? ! W. w' q3 L9 z+ K, m
! }5 _- ^. O# R
        0 p$ m6 n; K- t5 {% @. m

9 M$ U& J3 I2 l) R        申请渲染(字)
/ {* O: n# I; Q+ V3 i# Q; o/ {5 X6 V: S
        {
/ j5 k& c6 Y% k+ q" p
7 C0 N$ B  b4 x1 c& I+ M1 K                if(有这个字)/ Z$ u: r& L# q6 R- @4 z( k
" @: ~$ m; D3 X* }* `# C  `9 }
                        返回位置 . C# F% L2 f/ U8 o, @! s! Z" w
* C6 U, N0 r6 _+ E, S
                else. w% m+ X9 Y% o

* {' p6 R& x/ ?4 }/ j                {
6 l$ A( y% E/ c* e9 ^9 y0 s, l7 U2 r& p) X1 K
                        if(有空间)+ u! i' O4 }( G+ `3 r$ v5 \
8 ^3 z, ?# h  x: Y2 Z2 M: ^8 j3 B
                                画字 8 D% r; l- \- |" ^# u* k
3 J! ~1 [) C" R1 ]; Q4 m: z7 \2 A0 i
                        else
+ a+ [, q( s3 K% k, s5 ]
$ w" }+ a* s* c6 |8 \                            找不用的字//找不到就出错,没地方画了
4 S, @. |, c9 a# c) Q, R, M
3 V9 Z+ _  @, K' S: t( X! _1 Y9 C- s                                删除 在这个位置上画字 $ H- Q* ]) K8 R% }- U8 g

2 _8 f7 }! Q" e& d8 t                返回位置 , [8 @2 c1 v' ~3 ~& J' J
& _8 K1 x2 C8 Q. C2 _" v
                }- `9 K: k  k* R# G
- O+ |& |/ L$ g& r
        }
- e( R+ f3 p1 e( Z, Z$ U& q+ L8 L* `
        上面很直观把,大体就这个意思了,申请渲染的函数是inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )  const。去掉const改一改。得到 # s! C4 r' B: j& Y
) Q3 z9 s0 B% z5 q4 m
        a.申请渲染
1 B. e9 t8 P, m1 D8 c" t7 V6 K  `5 F# \" A
        inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )         5 h! B; U; O4 u& C6 M1 _
9 L2 x& W9 P$ L. X' L0 e+ @! ^1 {- \
        {! ]8 Q: ]* r4 d) T, Q3 Y0 g

% V+ |1 N  h( ]( }! N9 C" W& W                unsigned long idx = OGRE_GLYPH_INDEX(id);
. n/ J. b+ n4 U5 {% ~4 D6 t7 `. s5 a
                if(this->mType==FT_TRUETYPE)//ttf?
9 p3 X; h' }/ W/ B4 U4 H* l% J( Q+ E2 D5 m
                if(id>=161&&idx<OGRE_NUM_GLYPHS)//汉字?9 h$ Y3 X+ r5 |# g# e
' f9 i6 r: z) I. q7 j
                        if(!mTexCoords_v2[ idx ])//没有?
4 D0 T, \# [, H* l, p3 |$ W  n6 J4 C! T- C" F/ l$ t2 Z
                                setChar(id);//画字去 : o' ~& \1 a& Y: P/ P; j" j6 O9 X1 Z

$ ^6 T9 ^5 D% U5 D# t8 o- E. Q5 Y            
8 y% G3 I% j2 u6 c5 X* V0 D: G, N8 r, D. R; {' Q) [) d
            u1 = mTexCoords_u1[ idx ];% w% I! n/ [+ v4 S

; U  r, M% A6 q: O7 a            v1 = mTexCoords_v1[ idx ];; ?* A7 E* Z; R0 k% a

4 L, ?. }) n! O( N            u2 = mTexCoords_u2[ idx ];
8 M6 U5 {% V) R# \
% p+ ~6 ^+ u0 s* \* r! j            v2 = mTexCoords_v2[ idx ];
, w6 @4 @. Z& l0 \% o7 ?
& t+ U& T5 F' c9 P        }
$ ~/ ]1 |. Z" f) R5 [( ]% x  J7 b( ^8 A% q* T) Z% {2 N, ?% A
        b.画字等
9 [% Z6 F" M9 Z! N7 v
9 ]: D2 z: ]8 f' d        bool Font::setChar(unsigned long dwChar)+ b+ O% e, g% |! i
, A& {- o  H" x9 {; e
        {# H7 }: A# M  I/ }

# B6 G  y+ Z7 l2 T3 S, r( S                int j,k;
% W6 A: F. r0 K( t) {* T# h2 h
: ?# Q$ z8 J7 Y- v0 R                uchar* pDest;//操作数据的指针
3 `8 }( D* j4 H5 \0 i& N
! U& ^  N3 @8 z' N                mProportion=0.8;//不知为什么,总觉得中文都太扁平了,所以设置这个参数,在《让OGRE支持中文》中创造的参数
$ ]4 G. n  P$ c; k3 w8 h4 l8 K7 n1 F, }+ n$ U0 a7 x& r% ~' ^7 D
                Image::Rect  rect;//画字的位置
2 J0 q9 i2 x9 z& J" A3 M+ i6 J# X# b2 N5 l' a
                if(!mTTFMsg->getRect(rect)/*回头看看这个函数吧*/)//如果得不到空位置 7 ?* E& o4 G  Y
0 \/ N# w* A; [7 B& N* A& N
                {
7 B, E. c6 D% `1 @; S2 ^9 D, V( F0 B1 y# I6 o6 {- V& O6 F
                        for(int i=161;i<OGRE_NUM_GLYPHS;++i)//寻找不用的字 4 [# O9 ^! k* N& z, _" S4 o

/ i; D0 @6 a2 E" J                        {( ]2 \0 ^, A) d" p

, g9 @3 Z$ B- l. S$ {                                if(!mUsing&&mTexCoords_v2); l' g8 q9 P) G- @4 Y
2 e+ i+ f6 ?. Z) L% G
                                {
% a; [: ?, W* M- U
+ E0 y( O9 Y3 {' f( M7 K" P9 w                                        // 得到坐标
0 L- l6 F- a# w- y/ C2 l2 v& y! q$ x* I. o
                                        rect.left=mTexCoords_u1*512;
+ V: U# _4 a: r$ \% {% b; I3 T2 c9 @/ {1 {; S/ F- r
                                        rect.top=mTexCoords_v1*512;
0 M. g( {5 g# x$ s! l
. r  W0 i( J4 f) p5 O3 D$ u                                        rect.bottom=mTTFMsg->max.height;% K; [: e  J5 ?* k/ s& N, N

# q% U0 i* J  ~( A4 {& \% d1 n7 t                                        rect.right=mTTFMsg->max.width;
8 t  z. |1 s& n- ~; R- L" K2 h0 c3 k" t: x& M# P. u
  8 k# c( n8 e1 K0 g; o" ^( c
7 ]0 _9 B) z3 x& E
                                        ! G6 k' k- j: y! v3 [& |( y

6 l5 i& W! V  G, u( O4 G1 R5 i* v6 S                                       
6 D# q0 g0 S5 w+ o' N0 [5 z( i
- |2 l2 }+ W: O7 Z2 j, i" ^4 n                                
; s( i" A* U- G: L/ [5 G
$ P2 j( B, G/ P+ z: }- m6 f" ]! t1 J& e                                        //擦除(这段代码没有试验过,等做完输入的类在检查吧)
3 c! A2 I9 {0 V3 l$ Y$ X
- A5 U& i9 [! M  G( `& g                                        for( j = 0; j < mTTFMsg->max.height; j++ )
* \$ D+ b# m2 Q$ ~" G+ @3 _, T5 M. i- N+ [- q
                                        {
1 q' P. V; L2 T
8 a& k6 s0 W0 ]                                                pDest=mTTFMsg->imgchunk.getPtr();) l9 v- I7 M9 U0 t
" z! L- N/ W8 D6 W7 a0 g% I5 C
                                                pDest+=((j + rect.top)* (512*4)) + rect.left * 4;
4 g/ G6 p! f. J" d. v/ J
2 F2 r1 ]; K( O# F; _4 ^                                                memset(pDest,0,mTTFMsg->max.width*4);* Y( Q( J3 d9 v  i, l

2 b9 d* e0 A; i8 ~                                        }  [' C1 c$ D" D

  \$ c9 i  f/ p                                        mTexCoords_u1=mTexCoords_v1=mTexCoords_u2=mTexCoords_v2=0;
9 m! Z- ^- `1 E
2 o, w. S7 ]$ N/ V4 t$ [5 {& Q) [  / c! f; c) ^, A; ]0 i
& `( ^+ ^: v3 ~1 x9 B' V( E3 L) r8 ?9 K5 T
                                        break;" q5 g. V" W+ n
2 J( O8 P* q2 E6 ~+ G
                                }
( C) d) Q' ?2 _1 O; _" i
; O1 ?5 Y; x  G0 B                        }6 _) o0 e2 p- J, h$ r' ]; L
+ }8 Z5 D, D7 B$ j7 ~3 C0 D! l
                        
3 r+ S( S3 X' f' p0 m. D9 o) u( B# U$ u3 f
                        if(rect.top==-1)//啊啊啊啊啊啊啊啊啊,贴图竟然都用完了,没办法了,出错了 & d! ], W$ O2 {- ?0 k/ k

2 p3 u3 Z1 @% B6 l+ A                        {
  \! V8 `/ B) C+ W0 E
, ^% ~$ p$ e- J& K: h3 j+ V4 a                                LogManager::getSingleton().logMessage("你太贪婪了,用的汉字太多了,这是对你的惩罚."); - \. d! q9 U2 h. m& K. j" F
2 K9 D- s+ m; I. h. {4 V- z
                                return false;1 J/ [8 E* L: b2 I5 A2 l5 h5 g0 E

* j! O/ w  [, C1 G, U* X% M                        }7 A0 ^  z0 |9 V2 n7 [8 U
, G  C  N; T! b5 g
        7 Y3 g* E4 g/ g6 O3 Z
% ^* V* }4 W5 ?
                }
# L- {$ y. q2 X; y; D
' A5 ?) u! c* P  l# ^1 O4 z                        
: b' ]8 ~$ Z5 ~* i& U2 A' m) c1 a6 v
                . C, G& H# {. g* r. B1 C5 \0 [

+ }$ b+ Q; M& _" A' `# f                  //以下画字的都是招葫芦画瓢的, 4 n8 G: ^' K2 p+ ?. H
$ `2 [+ [4 K  ~9 r3 k) A: o6 W
                  FILE *fo_def = stdout;  [$ D7 q7 w5 d1 ~; z) f! z6 u- E( B. A

: \+ f; y' W. k7 E/ g* h                 FT_Error ftResult;( a. e- f* b8 l0 J3 A" l! q
8 E& x8 l8 k, R" p& {) X
  : g" F4 U; A# z( @4 q

7 H- U8 O, Y7 P% z6 z" g            // Load & render glyph
6 j: A2 o! D* z0 e: |4 N8 Q; ^, o: _2 |% L! q
                  " x2 Q* o5 {/ g* X
, B5 J# ^- P5 k- K
            ftResult = FT_Load_Char( mTTFMsg->face, unicodeMap[dwChar-161], FT_LOAD_RENDER );//读取字体 ( K0 u, }8 t( A4 \* K8 ^6 T2 ?( B, K
" ]. X1 J2 j) W6 x
            if (ftResult)' R, M2 ]& }- i
& h9 _, }5 r* ]7 y$ a  w! f( g3 g
            {) N1 T) G0 ^0 F% d% [& |2 y6 w
/ h; X  b) T$ n5 x# V9 N% g" H, c
                // problem loading this glyph, continue
: J& G5 v% b" V. q9 _, y/ a: F; n6 W- D- p
                LogManager::getSingleton().logMessage("Info: cannot load character " +1 `; b4 i1 k( t' R7 Z/ g

& h4 P' w: u; A9 r                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);
# W$ N; k/ f+ Z( ^( Q* P# N9 a1 t% K9 N& F, {; p
                return false;//如果错误跳过
& b# s6 {% s' Y  X8 G8 c
, b. l* D2 i0 K            }
# b) J9 @" t% |/ ?) F- V8 c4 G0 P" ^+ J6 O; \) Y) @; H
  2 H9 Z7 l- X1 @( d- n* w3 w; d  R

) x4 ]0 D' \8 q) `* c) A  j          unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;" G4 S1 n4 a) {) S- y+ k
2 w1 Q1 l' j  j9 z1 S2 F
                  // 位图指针
) s  J1 _7 |- S5 v& K4 e; _" w- `& ?0 F3 k# {0 P! l
            if (!buffer)
: U- a. o! v4 \6 U$ Q6 r% g( T1 [6 F  ^$ d" f2 x/ b" p
            {' X, ]  c" o8 [' h- y

1 B8 @' C2 Q4 `. U: I1 F! l4 ~8 }                // Yuck, FT didn't detect this but generated a null pointer!
  Q4 z# G& W/ }' W3 D; T
# |# ~7 E5 D8 P* [                LogManager::getSingleton().logMessage("Info: 1111Freetype returned null for character " +0 r! H6 r3 \$ L7 p3 O

. r, g7 F3 N4 b                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);
, t: D+ Q! ~* k( e  @: y4 h+ B5 c  Z6 C- Q( P! e; z
                return false;//如果得不到跳过
  ^. l6 L! {" S, e; L% g. j
; t2 H5 B6 w+ E' _5 m            }' d5 O$ E, g  `. @
& K. Q0 C2 W# G
  
; P0 w1 k" B% `
( z% @+ W; g, K8 z2 N) b& M                         int y_bearnig = ( mTTFMsg->max.bear) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );+ e3 }* A! b* g$ r% p; \
$ P* P3 t% N/ D; X3 f
      
7 }: V/ g" k9 Q( p% g! d1 C& S3 ~8 U1 W* I- x% L
                        
$ I+ A: d2 q7 `& i. `
: C* R# j) Q+ j* L; U, I            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )
- z4 X/ _1 N/ s! a, f1 z
* r9 D/ [5 a/ S, D3 w            {- e$ p* N0 Y' K' ?* w
+ g. \. H0 |6 J% ~
                int row = j + rect.top+y_bearnig;
4 t* N. y0 H$ Q. X& y5 m) R7 K
; k2 c6 y/ a+ K! C, j, l                int col = rect.left;//列
" `# \- a+ t8 T! a- Y2 a% }4 E
: P% e$ T  P- k8 u2 f9 \5 U* Y, |                                pDest=mTTFMsg->imgchunk.getPtr();" m0 |. c* E( u, u: V* e- x

- U$ H( L& w; ^* e0 L. z5 P  ( T: W4 u; g, u3 u& `$ Z
! \( P8 G) E4 Y& j) h7 m
                        " _4 \0 b" B1 P: {) x
5 Y% S; i. Z8 I9 O5 ~& ^
                                pDest+=(row * (512*4)) + col * 4;- J$ R: B3 I3 O

1 @- c7 c. w& Z) j* G% c7 [3 P               for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//每行的点 $ l7 d9 g: L: I1 }' J9 a
1 c/ N* c! o% P4 k
                {
+ I2 h# h6 @1 ]- |; G6 b' i# S8 H( j* h/ J. ~
                    if (mAntialiasColour)$ p4 T" {3 J$ }
- L; T: i  @' o' F
                    {& G0 ?0 d3 m) M* |. s7 c2 G

/ }1 v6 K9 \) }$ s/ E                        // Use the same greyscale pixel for all components RGBA
5 i. A' F& g; ~/ H
! d8 j+ @% w5 |) y0 t                                                        *pDest++= *buffer;# O; b8 i% a4 f3 W6 j

* @; z3 N; k) T1 M: N: w0 A3 N                            *pDest++= *buffer;
  E1 M3 k# T; c+ {) ^- J! y
$ s# z( u" C5 S  V; S! |                            *pDest++= *buffer;  v' [2 }# ]: P% T  x

* I  U% W7 _" m5 I& n6 x* ~* {  ]                    }
" j5 u5 u+ v4 t7 i- z8 a8 T5 C5 t5 [% l- a) |5 M6 \
                    else
: t( t: D% `' `1 W& g% R
* {- l& r3 ~, q: S                    {
1 m% ^* O. z& e
4 C5 _6 U( v, ?8 d; _! T: m* n6 y                        // Clamp colour to full white or off
. {) T( u5 C; {: e# z& G2 i! ~2 e5 u2 \  i& y9 {
                        if (*buffer > 0); y& h3 s' |# y# y5 D# S5 H

/ Z6 O) D; f+ z+ {( m# {                        {
4 f# A4 ?. U& Y7 n' d* v" n2 c6 B+ {0 b7 J
                            *pDest++= 0xFF;+ v8 M' M% b9 t3 o

. A/ E5 d9 N' R; s" e2 j/ W% K, d                            *pDest++= 0xFF;
  a/ n8 J3 D! N! `9 S7 l$ w' f
$ \, a; e1 T7 _9 w" j  G/ F! y                            *pDest++= 0xFF;
7 p) v# O: x( m- W3 Q/ Q6 w
; d6 \, g) X+ k2 b  |                        }
  c) g  I; ^5 J& g+ _0 U. Q! B; J
                        else
1 u1 Q; R  M3 _* Q  F2 [. d' U6 Q( Q
: |! o! z3 W2 B) Z: e                        {2 o3 w, y9 g! k
; Z8 z4 f) ]( \- g5 F2 i" }" l7 D4 }1 K
                            *pDest++= 0;1 o: `4 A. {% w8 s6 {- \8 F) i
# s/ ^) I/ u2 c5 U5 F
                            *pDest++= 0;. _2 U) d. j( J( G' H1 ^& Z
- R) F* k" L- c/ Y6 U" D
                            *pDest++= 0;- e" l% w. `2 J) W3 E2 V
, X0 e1 b9 x( Z9 o. R! {) y
                        }! g- b, s4 W- x0 @4 t/ n

( S# [: N  M; x4 I                    }% e( O, M4 d* p3 k5 ~
7 x2 F+ h" N' M
                    // Always use the greyscale value for alpha   J  F* h! H, x2 k4 i

# I5 W2 p& F9 C' f. w' ?" J                                        ) |$ y$ g; \" `) C+ @" f

: D/ [6 H2 w4 o. G4 U                                //      LogManager::getSingleton().logMessage(StringConverter::toString(*buffer)+"is cool");
0 T# {9 K4 |% ]
! P* E2 l9 M3 |; n5 _                    *pDest++= *buffer++;, R$ ?6 Q) o( P2 n% Y$ F, J

; q, ]6 p% j: z                }( S+ I1 z" [! P% T% k, A; M* m
$ A; o1 w- n& s/ l! Z; h
                                - z/ y7 S$ ~% Q! u) P) [
8 \' Y/ L  B; f- g+ h/ }
                        }4 C  l+ H3 j  |0 @/ [* o
! Y4 n' F7 E& h! p1 t6 q0 w, y
                        // 设置位置 4 [% y( g8 a$ ]: f  _6 L
* d$ T/ r* Q# d
                        this->setGlyphTexCoords( dwChar,
9 {) U4 R+ y  h
4 Z9 \( A( j! H, }                                 (Real)rect.left / 512.0f,  // u1
4 ~! S/ K. [, P3 k8 D3 m1 c3 o- }! l7 F. A  `1 n5 m
                                (Real)rect.top / 512.0f,  // v1( S0 n' }8 ^, o$ ~% Z# A
) p. s* ^2 O& S3 ?2 s  i) ~/ E% v# ]
                                (Real)( rect.left + (mTTFMsg->face->glyph->advance.x >> 6) ) / 512.0f, // u2
6 `' G6 N$ f- e4 N  F& l  [& [7 l# M
                                (Real)( rect.top + rect.bottom ) / 512.0f // v2
& A9 o' Y, t4 G) `4 B. N7 i9 E' Q# ~) [- t& R4 |8 l! x- \' L# g
                                        );
& n8 s1 B; z. l& i- B
3 W2 m& m: {9 c! _5 ~. N  Y) m                mTTFMsg->dirty=true;//贴图需要更新 2 Y# R" _8 L9 ?" L
1 H8 Y7 y3 ?0 T0 C1 j- p' y8 W9 \
                return true;/ X0 p# {) F7 o* ?3 {
7 g( ~8 S# x' P2 d$ o' a: h4 {0 \
        }
9 y1 E/ d: ~: {* P
. ]: |) E+ ^7 X6 v# c  ( T: x* _) c1 |, H

. B4 K5 Y* w$ g(4) 8 I2 O9 s. [0 Q) Y- x8 R" `7 c+ |8 W

4 _/ G6 N; U2 I/ k, L3 G0 P3 q        松口气吧,繁重的工作都做完了,就是更新贴图了。
7 G$ [0 J: R! q% Q5 {; d+ H# q7 Q( `
        Font类中~
- @, _6 S9 P8 O1 ]! {# R2 N# E' ^+ ^7 p4 w4 D) J) U
        inline void write()
( {: w) Z  ?5 b! J7 z& d5 R0 b5 ]5 c: n2 j, o' i, g
                {* Q+ |% n/ E' r* t5 s# m8 z6 S' `8 B

1 N  s6 Z9 x9 Z+ D6 W  t* v                        if(mTTFMsg->dirty)
; I! N3 \( E8 l6 {. ?5 v/ k
6 C. Z5 e/ _: p                        {      
6 ?" Z& r; E! J6 v5 k
5 L4 a  a8 O; h1 ?" Z" G                                // 重新载入贴图,顺便说一句,类似功能的函数还有 " d. y% w+ Q, b6 w) P' q
/ B: E& R. S5 F  n& F! a
                                //virtual void  blitToTexture (const Image &src, unsigned uStartX, unsigned uStartY)=0
1 Z& ~! B! d; S1 G1 u) [- A8 y! Y8 I- Z9 S* R
                                //和virtual void  blitImage (const Image &src, const Image::Rect imgRect, const Image::Rect texRect)0 Z" t2 n- K4 K( z/ j+ N3 {4 |

% V& X1 c: K6 {* d. E: b, X7 t. \                                //不过blitToTexture()在ogre-win32-v0-14-0之前没有实现,没有尝试使用。 blitImage()就算到现在也没有实现。 4 d2 F% [! ?# O

3 e& v) y) S5 b, I/ L9 m. p  
, D/ ~3 A4 q7 l8 l! j0 V1 f, W! Y, t: K" p/ u
                                TextureManager::getSingleton().unload ( mName + "Texture");
/ y1 b$ ?6 u9 K% G* P; d! o8 X. Q9 P
: `* S& u0 Q, f0 Y5 C! M                                TextureManager::getSingleton().loadRawData ( mName + "Texture" , mTTFMsg->imgchunk,512, 512,PF_A8R8G8B8, TEX_TYPE_2D, 0  );0 O+ O$ U" n% f
8 u' ]6 a6 Q: m+ b0 B
                                mTTFMsg->dirty=false;
0 A0 G4 Y' m( p  T* l6 S1 v9 Q( e, ]1 C7 [% B6 L% p8 g4 p; B5 U
                        }
( m4 b' g8 @. j0 o. V3 F
6 n  J! ^7 X9 o# u$ G0 t  A                } ( x% i4 j$ I' v; T

9 a  N6 r! f4 U$ ]3 d  
2 F7 [) ^- W. X/ j# q# s
6 n; f* I/ p' W5 t* h         在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。 : `3 {. z& L( d, y9 y! n
% u6 I# m2 O. u; Z8 Y
  
3 f4 O' C" L8 Q0 d) s1 L4 k! E+ Z3 H
  8 R8 Y  P2 j( R7 N

" X7 ]0 d" x. a8 D3 Y3 D4.结果。
1 J. D# O6 a6 f* z  x/ ^- Q9 g0 x* `: N$ W; a2 k8 m- c/ @
        好长阿,写了好长。虽然多是代码,但写注释也很累啊。重温了这些天的工作结果。就像上一篇一样“在OpenGL和DX9.0中成功的支持了中文,但是DX7.0中竟然出现了运行错误,具体问题还不清楚,还望各位高手指教。”。不过本来OGRE就不怎么支持DX7的,不管了吧。OpenGL中渲染的比DX9.0清晰,是我的显卡的原因么?以上的winXp+vs2003.net+艾尔沙980se通过~。。 9 {2 l( k" ]( o3 ~
5 C: a# B5 X: V* i6 F
        顺便说两句,上次发表了拙作,没想到好多朋友和高人们找到了我。甚至联系到了一个南方的公司,说要做一个引擎支持中文的方面。但是卖完400多的火车票之后竟然因为住房问题作废了,5555,退票少了80元啊。还是自己差阿,如果再多学点可能就能要我了把~。努力吧,争取写《让OGRE支持中文》三部曲。
% l3 z7 w+ b# R. Q5 A; b6 v- e) r$ P% P5 H( p8 J$ @
        下一篇应该是《可以输入中文了》。
; c$ |* T: H2 D+ R7 ~, M% B- H, l% S1 o# z% W+ v7 x8 j$ j% P, Q' k8 o
        也可能写不出来的~~~~~~~~~~~~~~~~~~~~    + \4 ~; x# [" a2 _4 i: x( E. l
% `3 t+ ^3 m4 Z; ~- ~. _% ]7 U
    相关文件 / x& E  `0 g  X3 E. f% e
+ w, |$ x1 T# r
    chinese.fontdef//字体信息文件 放在资源文件加中
% C" b1 o7 F* s& L
, Q2 T- T( Y: B  S; W' }; A    font.png//字体图片 放在资源文件加中 + c: I5 W& |# l# m
5 }2 u% Z& |2 |1 ^3 _4 z) j
  
7 C& l- i7 V+ L$ B3 K2 Y; c1 g. s. o8 A% a6 t
    OgreFont.cpp
) k4 y! q" v9 Y& B
1 n$ C- T0 S& r" N: s0 C    OgreFont.h2 M( u; p1 V; c( S

/ H, g' _4 G- X" l    OgreFontManager.cpp6 w: e* U# y& n5 t2 X& n7 T

+ a1 c" h, ~2 q3 ~+ {* [  v4 [* E    OgreTextAreaGuiElement.cpp
  [, d- j& z: P4 B( K( F
# F9 h9 g) Y% o% V, G/ x    //上面文件覆盖同名文件 就可以 先备份 + B- ^( W0 G* u. [: }4 ^

9 k8 [0 s# c; U   
1 N' c$ R/ ~3 F+ v' y0 L9 u& v$ c/ X# P9 ?7 }
   solo5.ttf//这个是一个中文ttf 我直接替换了原来的ttf6 M& ~- p2 O7 M% W: x! D$ r3 s6 @0 D& g

9 F; l( R( s4 x/ l' a( B' A/ E& {2 v   unicodemap.h//这个重要,是换算unicode码的数组(文中提到)
( N+ ~7 `7 z4 F% U
- O9 B: z9 g2 g. O, f( }' P! L3 n  , m1 P6 b8 W1 r/ G3 [3 Y) X

& C2 j6 `0 {& D; V1 F/ H这个是在ogre-win32-v0-14-0基础上改的(上次是ogre-win32-v0-13-1),
/ E& Z  b# \0 t6 M
) K2 _. U8 u* P7 _3 O请到http://sourceforge.net/projects/ogre/下载
9 P) Q8 I8 a1 X5 _% }0 _2 l
  M* e( j5 C' A/ {+ p* R配套档案下载:http://www.gameres.com/Articles/ ... /ttf.files/file.rar / G3 w/ `! O5 Y
5 G8 [9 g7 M. E
免费打工仔QQ:1850070
) w. z8 k( q1 y: N7 z5 }4 n  f
! B/ y1 U; b# v4 S$ }  C! pFrom: GameRes
" s0 X3 }/ r' @" T; [+ ]# w3 d' s$ ~: U$ K
http://www.gameres.com, a/ Y7 g& D0 B- B' N1 d8 w5 r3 g
* }: f$ c+ c5 j" T, M, T
上面图中“免费打工仔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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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