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

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

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

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

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

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

开源的图形渲染引擎OGRE(3) --让OGRE支持中文TTF字体! S! a# h, H8 |1 g% J' p/ Y

% Y0 M4 P: R6 F0.还是前言 / |4 W4 x  Z" I" T/ V: N
; i2 `( X$ i' b* F0 \) O8 x9 R
        如果你希望能看懂这篇文章,请先确定你已经看到了《让OGRE支持中文》(http://www.gameres.com/Articles/Program/Visual/3D/OgreSupChn.htm),因为本文是在上一篇文章的基础上写的,并且假设文件都已经按照上一篇文章进行了手术。但是如果你只想简单的使用TTF字体,只要下载本文附带的文件,重新编译就可以了。
9 o, r4 J4 P- u- O* B) L* I- }1 i' y( D0 B. s' \
1.检讨 5 {* L) v. U# ]- y" z# a' M/ [

; l6 o  c! R1 W" U1 n        正如上回说的,我们已经实现了一个位图的字体。但是当冷静下来思考时,就能发现这种方法的诸多缺陷。读入一个2048*2048的位图,等于在显存中保存一个2048*2048的贴图,不说是否所有显卡都支持这么大的贴图,单是每个Font字体类吃显存的胃口,就足以令人心惊肉跳。如果定义足够多的字体类,我想你的游戏的配置要求,在某些方面足以超过《DOOM3》了。
/ Q' |* G# Y# `% f3 S
& E- z* S1 G% E1 S3 J& T. n5 N. H        而且这并不是唯一的缺陷,文字大小相对于位图大小比例相差太大,导致浮点数的文字位置误差很大,你可以在一个文字旁边看到其他文字的影子。(虽然可以通过增加文字间距来解决。)还有点阵字体本身的缺陷,就是字形单一,不适合放大缩小,一些文字边缘的马赛克,足以熄灭任何玩家的投入感。 ; H. M8 b0 T- }& z. C0 Y
, ]4 m) y" k) _% @5 {" ^# y
        似乎TTF是唯一的解决之道。
* M* `" j- I9 {; w: E" K# e' V( `4 }: Q# \
2.基本知识
* {; ^  [* B! o  |  e4 n% c& ~: Y: [& p. l6 S
(1)TTF字体。
( ?2 r, }) f9 j) Z9 r* E9 [% M
. k7 [7 i, K1 M        TTF是一种矢量字库。我们经常可以听到矢量这个词,像是FLASH中的矢量图形,在100*100分辨率下制作的flash,就算它放大为全屏,显示出的画面也不会出现马赛克。所谓矢量,其实说白了就是用点和线来描述图形,这样,在图形需要放大的时候,只要把所有这个图形的点和线放大相应的倍数就可以了。而且,在网站上有很多的TTF字库可以下载,或者你可以去买一些专门的字库光盘。然后在你发行你精心制作的游戏时,可以顺便捎上这些后缀为.ttf的文件就行了。包括Quake这样的惊世之作,也都是用的TTF字库。 - n- s: G' Y, _7 [1 h# j* l

( t1 h; P1 D7 ~; W(2)FreeType2库
1 w2 w1 w  K# P
% M! {5 W: W4 M8 H. |" h        在http://www.freetype.org,有一个FreeType的免费库,而且是OpenSource的。它目前有2个版本:1.0和2.0。其区别在于,1.0只能读取TTF格式的,而2.0支持更多的文件格式,在使用它之前请详细阅读所要遵循的Licence,以下是摘自FreeType2.0对字库的支持列表:
4 \7 A: F3 v! P6 K$ j0 j$ ?2 Y, S2 e; \1 T  h5 |
        TrueType fonts (and collections) 1 U9 ]+ l! u5 V
; @7 |, o2 {( v" f! ]: T3 d0 Q
        Type 1 fonts
9 K- z6 Y8 Q6 y# Z2 K$ L5 v9 M# }! a
        CID-keyed Type 1 fonts
7 h4 b/ N6 a' J2 `9 ~1 X. m% @
3 |  `; f# w/ D        CFF fonts & Q3 F3 m" l( d
- O9 y: g/ v. u! O; s( [
        OpenType fonts (both TrueType and CFF variants)
, [' m8 r' M! m, G" I0 {1 Q5 B8 X9 z7 \. q& |' H0 C
        SFNT-based bitmap fonts
4 L: g! `! H4 e1 P1 `' Q2 X
+ g! V6 Z9 ^1 Z5 E% `8 |        X11 PCF fonts 8 f5 A, Q' l6 N

3 n# U1 ^* \' C* Y; B        Windows FNT fonts
5 X5 l! j3 y; P9 e2 d
1 f7 N& n: W$ h: C8 {8 z(3)“主体思想” , P$ L, c  T; U7 h5 T

- O( O) v! a1 x8 l, {6 m        请参照炎龙工作室的《游戏中汉字显示的实现与技巧》这篇文章,可惜使用的是Windows API,作者千里马肝,上网上搜一下吧。
! E9 L$ o+ G! D4 M
4 \2 U& w3 w2 I+ X        附带说一句,上面两条都是直接从这文章中剪切下来的,>_<  不要骂我啊,不知道算不算侵权呢。 ( ]4 a" c: U9 [; Q2 X& j
! g; k  }' k" N" ^
3.动手术---比你想象的要麻烦 0 ]0 j- B# r: r% i$ q
(1)
* y" `* I; V2 d        首先要告诉字体类,我们下一次渲染需要哪些字。以便字体类可以在需要的时候释放不使用的字体。
  f8 N! H9 h4 U8 H9 D$ i2 |
5 H# l1 n- F: e; u) l# J        在Font类中~
' W, B4 P1 k; U/ a  A  l' T1 C0 ?- _" r( |
        a.增加数据 bool mUsing[OGRE_NUM_GLYPHS]; 用来标记文字是否使用。
( E; {& v9 r& X2 M# Q( c% O, l: s# \5 d' s  i7 b- O8 F) j
        b.增加函数 ; K6 T$ j, w0 j

% c5 q, w/ A* G9 t                inline void setUsing(std::vector<unsigned long>& caption)- B3 y9 ^5 ^& s( g5 G) C
" Z1 x- ]7 V6 u, i) \- _
                {
, `+ W) o" V+ ^
! f4 i1 `# B6 l& i0 e                        memset(this->mUsing,0,sizeof(this->mUsing));
8 f( p' U5 n$ F. ?' ?* h- Q4 ^5 |( [4 A  T, |* k3 z& A
                        std::vector<unsigned long>::iterator it;7 I2 ?. J# V, ~  s* n( n4 m
( t" u& o0 A" ^! n) K4 Z) Q! {3 [
                        for(it=caption.begin();it!=caption.end();++it)4 I' F+ {5 {7 i1 F& R

8 `# p6 S, Q( e                        {5 ?; d/ {8 g/ p5 f+ A' u) n; ]

7 f" P& o+ _; t$ ]( W, }- b                                if(OGRE_GLYPH_INDEX(*it)<OGRE_NUM_GLYPHS)# U) h1 _% q( y5 I- O

, _( @# r* k. D" [  k1 m7 t                                this->mUsing[OGRE_GLYPH_INDEX(*it)]=1;//标记文字为使用
( l, p' U' t! D, X& i; v/ u+ \7 U. h& D) {; @, ~8 k9 X- y  a
                        }
6 Y  o( X, M# L! r9 u' s8 H. a- c/ F! B! m7 }& n
                }. w6 I1 N; a4 D
. i& ^5 }' A# }3 v, o$ l$ l
        并在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。
' v# s" X# M% ?2 j, C(2) 8 s3 d- Y8 X2 I2 \2 R( Z
, g( w; ~7 D' k% ^6 E
        然后是修改void Font::createTextureFromFont(void);
6 |) Y( ~( g& T" I3 q  I
0 d% P8 l4 u. S, H: k' E        Font类是通过void Font::createTextureFromFont(void)来把通过FreeType2分析好的英文字画在一个2^n*2^n的贴图上,然后再保存英文字的位置。 5 D3 _$ \+ N: U$ S* @( s

  @4 j" p- q. M        我们需要修改的是:
6 ]" }- e! X" w9 `* A$ n! `+ u7 i- H
        a.从函数中分离并保存画字的FreeType2和辅助变量。我们通过一个类来保存和处理这些变量。 9 m6 o* y; l4 k+ }

- ], t: H5 Z+ S. k& @* P% ]        class TTFMsg. s' }4 w0 [; F! r6 W+ W
8 w: D) N4 T; E& `! w0 g
                {( j/ n9 ]" N1 T
1 u# D: \( l: E
                        class Max//类中类,用来保存几个"最大",
/ q8 D9 r. q) M
$ x7 E- x) J+ |: T                        {
! R1 H6 C; C+ l' c) F0 c" ^8 Y0 u/ W1 i9 k0 k' K+ F% k  P
                                int nothing;//这个是用来占位的,没意义,反正没他就运行出错,可能和数据对齐有关吧。 ; Z/ t- D8 z# p+ r6 m% Q! _- v1 l% j  D

! @6 N2 |1 W% \( B% }                        public:
: `* B0 q/ j  v5 `5 n* P                                int height;//文字最大高度 % N( D) ]% m1 x7 l! P2 v
                                int width;//最大宽度
4 j8 |" v8 Y; c# ?" Z                                int bear;//最大空隙?
" m2 Z( c. ?8 f4 w, d                        };' P0 e+ t' d3 W# O8 a1 G
                public:
; }! h% j' S) o7 \                        FT_Library ftLibrary;//FreeType2用 5 R( w/ |  n! U2 j& _# v# W! _
                        FT_Face face;//FreeType2接口? $ x- W- \, P  L8 M. a
                        uint char_spacer;//文字空隙 . J& X: X0 F" a, \" e6 K4 R
                        SDDataChunk ttfchunk;//数据块,用来保存ttf信息 5 z4 o% P. V3 q
                        FT_F26Dot6 ftSize;//FreeType2字体大小
% s; ?  _  o% V6 }4 Y                        std::pair<uint,uint> point;//在位图上画字的点
* o! ^$ z& p- G' f3 S+ w2 @" {                        SDDataChunk imgchunk;//数据块,用来保存位图信息 9 @4 m/ M9 |6 h9 I
                        bool dirty;//标记,看是否需要更新贴图
/ X3 {* L" ?( w                        Max max;//几个最大
7 c% l8 K/ j5 t% x6 Z2 X3 }
5 U7 c7 `! _& |) h# x2 i                        inline bool init(Font*  font) //这个是初始化函数在void Font::createTextureFromFont(void);中调用.
* X1 y. U9 C% @7 g
/ I& [9 o  V1 i0 E2 w$ O                        {       % v; M. d( w7 u
4 s, c/ k! l0 @( V" C  @% I9 W
                                //以下都是初始化,大部分都是从void Font::createTextureFromFont(void);移植过来的
1 S9 ?6 x/ t$ |6 a7 S3 j3 ?, U3 u
+ W9 F% [# p# U4 o) w- f1 w                                dirty=false;0 I$ q- O, f' E& Z

/ U: h4 Z& Q0 p; v* @                                if( FT_Init_FreeType( &ftLibrary ) )
; h. Z/ J0 {1 J( w( _8 t/ i
# T8 C) ^4 y  S                                  Except( Exception::ERR_INTERNAL_ERROR, "Could not init FreeType library!",
9 G' Y$ B; H1 Q5 E1 m$ L
- m& R! Z7 E$ O1 ~* X' ^( O                                "Font::Font");3 F7 v/ s" w9 X2 I% U

. ~! {/ B6 b/ J* r3 O% t4 ?               
2 A# w; h8 [% b6 j0 H' ~8 ?/ W6 V$ L! L/ U
                                char_spacer= 5;* C& h5 ]1 H* v, A1 u

2 _! i3 f4 v7 |                                FontManager::getSingleton()._findResourceData(font->mSource,ttfchunk);
- ~. t9 i* {4 F7 y  m4 ~' F0 Y
! E! a) G# }/ M! b                                if( FT_New_Memory_Face( ftLibrary, ttfchunk.getPtr(), (FT_Long)ttfchunk.getSize() , 0, &face ) )
' J) E+ J( e) g$ e. D9 H
5 Z  |$ r, {2 G0 [) E; l& R0 i% @7 D                                         Except( Exception::ERR_INTERNAL_ERROR, 1 z3 Y- E- R, J5 Y. E
$ A2 [) }( `9 L, b5 M
                                        "Could not open font face!", "Font::createTextureFromFont" );
+ r4 K+ w( ?+ I1 r3 G
0 x  I. V/ X8 e& J6 ?5 B                                ftSize = (FT_F26Dot6)(font->mTtfSize * (1 << 6));
3 S7 \/ {, x4 {# n. M8 z$ ^+ d, |( n6 f# a0 S% E, ?  J$ ?
                                if( FT_Set_Char_Size( face, ftSize, 0, font->mTtfResolution, 0 ) )
* ~( l1 w1 j% A3 |5 A: y8 F
/ D" W  ^6 e0 d' P                                        Except( Exception::ERR_INTERNAL_ERROR, 4 w( S; N- Y9 `

+ j  h  e+ w6 q  p9 j: |0 x                                        "Could not set char size!", "Font::createTextureFromFont" );
$ U* _. {/ f4 Q5 J. [( X
' p% r9 X. g$ o! \( K  5 A! K& V! V7 b0 ]( V" B
4 b( E' e" `& N% b2 Z2 X4 w, p
                                return true;& g  U: O1 g" i5 j  c2 ^/ V
- x. ]& C: d3 L, h1 h# S
                        }- z1 p; A3 Z3 b2 O4 \3 g
7 C8 s, f3 y" N/ L' C3 ]3 x7 n
                        inline bool done()
. {# u# U; z: ]- z5 F; [' P5 X5 J! U, @4 d/ g# z' I9 E% {
                        {0 |+ ]9 _/ k9 a4 L6 u1 F

: P1 y0 D' w9 ]) w% A                                //在Font的解构函数中调用的,本来应该调用下面两个函数,但是不知道为什么一调用就出错,不用倒没事。
5 _" a: N3 N, m  m) P) N) F( m/ U6 r4 M
                                //FT_Done_Face(face);
2 ]6 b7 v) h' S5 S$ G% S7 S4 r5 K; O  T$ J5 \, l9 @
                                //FT_Done_FreeType(ftLibrary);: d, [6 A1 C4 j: ?

$ {" D" P& d. R' V' J* m                                return true;: C0 ^( F5 Q9 H0 R
7 s% Q# f' V/ {" o7 I2 j( V3 t
                        }
- ~8 h7 s3 ~, ^1 i4 \3 a
, Z. z; r5 W1 H4 n# Q( N                        inline bool getRect(Image::Rect & rect)//这个函数以后用的,是用来找到可以画字的贴图的空的位置 - @, W$ E- |. R# O. W( i
: ]! l) ^2 A' I; u6 M
                        {
. X$ t( E4 _2 U, L# e6 H+ N3 t* p- B: [/ F( L! g! Y1 m
                                if(511<point.second+max.height+char_spacer)
. Y# ~, l6 K' e0 i1 d: N- i7 L( F  H) R$ r! A+ j! B
                                {
& x1 R# b$ c! b* [& L0 N* O4 }$ h: u9 @* g
                                        rect.right=rect.top=rect.left=rect.bottom=-1;% g# \1 L* o+ b0 d9 e  u

9 W+ J; w& u( e" O( S* `1 \                                        return false;# d! ?' Y* N+ m  B7 K' Z. L) N
5 O, c6 f7 Q, |/ p9 r
                                }
3 [% E  p- H! u0 p& ~- N# J$ `3 s, G: b8 Z/ z4 Q+ X! @( _
                                if(511<point.first+max.width+char_spacer)) ]. S- f6 Y7 M
  }( Q; \; P. r2 U6 j' \. F% E
                                {6 r9 f* z( P: P8 v8 ]
0 r( z2 Z5 H; Y) b) n. Q
                                        6 Y2 V  ]( q5 h
+ c* F4 y! s' [. a# ^! n
                                        point.second+=max.width+char_spacer;1 c3 S6 s/ w9 }. |: I, j. ]( B

' J& d0 ?; a/ v5 L' i) r                                        point.first=0;
3 P1 ~6 W% [, _6 X
! C! V/ ~% p1 l- F6 l  w) D( h                                        if(511<point.second+max.height+char_spacer); O, N) c2 N; X

% ]: G2 l* f% @) O                                        {0 n& `' R+ O- V" D+ u% f
  y0 V+ H8 `( |
                                       
4 L" e9 P9 P. W' s( a' s  T0 R: ?( i! n/ [  ]$ [2 }
                                                rect.right=rect.top=rect.left=rect.bottom=-1;, k: G! F) x; P& ?) \6 w: ^
& s! |' s; m, L) b3 A& r1 O6 Z1 B
                                                return false;$ H/ O( S6 g( y* v

0 P, p- e; ~& E1 ]- G/ j2 g1 ~                                        }
: g' k7 w( P" V1 o. y! `  M# Q( V& m0 E, q3 |
                                }7 p+ O8 P' S8 i  x0 V6 ^
5 a$ h# }: ?% H+ g# @2 Q
                                rect.left=point.first;
4 l6 M" q' t6 s( e( Q. W( _% B& e" p3 f$ i9 `
                                rect.top=point.second;6 i% q) M( ?3 x# S$ @' G5 d

5 a1 f5 g! Q6 L) W                                rect.bottom=max.height;+ J2 k6 }$ ?' b! z! o1 I

6 o) l0 c  m. r/ G7 c, H                                rect.right=max.width;( n5 \) [1 X4 F. g. Y( `; W3 m8 @' e
. ?, y% t; g; l, J
                                point.first+=max.width+char_spacer;1 O7 c; H: j  x) n' b  I4 u
0 H2 r, D! e5 B' t9 u/ i
                                return true;  u+ T1 ^2 d, o+ \
( K7 r( L/ ]9 k1 v( j
                        }+ C9 V" z. Q2 ~) A/ U" S3 b

' a( F5 _4 e& T; S- F" H, {& b                };
3 ?& j( w; ?9 j/ F% j- F! o6 g3 v9 n- T& [# T
        上面的类定义在Font类中,在Font中增加 TTFMsg * mTTFMsg 数据,并在构造函数中 mTTFMsg=new TTFMsg;
0 `% o0 u" m2 Y" i1 Z% R1 g1 v+ {5 \
, V) `  ~8 O5 z! @0 Y4 v" `/ C' d' T- ^        
9 G5 e% B9 i7 |7 c
2 a7 f' B2 F6 O5 V: n! A2 P% d        正是修改void Font::createTextureFromFont(void);函数,主要几点,首先是分离出很多变量和构造到TTFMsg类中了,然后是贴图从2^n*2^n变成固定的512*512,为什么要这个数字呢,因为256太小(废话了)。能保证512*512大小的文本区不会出现不够画字的情况(所有英文+符号+没有重复的汉字),这个安全区域基本上是够用的。(什么,你要画满屏幕的汉字?哪你自己看着改吧。)还有一个重要功能是,要找100个汉字,找出最高和最宽和最大空隙作参考。修改完成这个样子了~) `; w! X7 e1 c) o8 F

  D- p9 U/ c4 k8 l5 k3 E    void Font::createTextureFromFont(void)  T+ c7 l( d% R3 G2 Z

8 Y# q+ U" M' e0 e+ x, X$ E/ s    {( g* [/ q& @4 x$ y+ T# q5 r, u

4 k6 V. m! Z5 {) w& w$ A. D        mTTFMsg->init(this);//初始化FreeType2. J' W% Z) e& C1 |( P; |6 M5 Y
9 _% T) e2 `4 G! V& U0 F
        uint i, l, m, n;
3 Y0 {$ ], z6 q0 ]
$ B* g' r8 w& r; n        int j, k;: Y  p: n6 b  k) p8 o
0 E7 d( X* X' ~0 |1 W$ F2 s3 @9 V
  
; h( F$ l0 `( A3 X& h9 U: ]" a$ `% P+ f# h+ b- \
       / R" L) l* K5 \

  O7 \! C& y) a8 |$ [: {; d$ F        FILE *fo_def = stdout;//啥意思?我看不明白 7 f& m7 g' C/ L7 h
" l) ^( R* x5 ^3 P# U' e
  ' N# U  W. U% a

' b0 J- G! r: A6 Y4 ~$ `5 Y        int max_height = 0, max_width = 0, max_bear = 0;
% P" a3 q. h3 r, c& ~4 D$ a9 |3 Y6 {1 o+ i7 _
  3 f- x3 H2 {8 O0 P8 H# z

! a( \: v" d- {  V6 g+ m0 f        uint startGlyph = 33;
4 `  r1 F+ Z( I* O- w" s2 r) j7 l
        uint endGlyph = 167;
+ Z# d  w- y' I& e& s, d& }) q" G1 c4 n& J4 u1 O: f
  
5 a' F  t" e; d( Y5 ]- u1 w% C1 U. a7 z4 i/ ?8 {: X. n) C
        // 找英文的找出最高和最宽和最大空隙 1 r+ A% L! q2 d. a+ I/ }0 V+ e

' h, n. @) X6 ?6 Q; O4 S9 X2 @  |        // Calculate maximum width, height and bearing
1 J' B2 H: n. H* e# W
2 A, s4 n  T# e, w( G        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )
6 c0 m) |9 c# E( a, y& L
+ m. H! \" p1 X$ \        {8 c0 u$ s9 W! ]! Z' [2 \) M) h

/ b4 T6 S/ Y: _8 {2 P. h: V: b            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );4 o/ d9 ], z- S. f9 k8 R
$ C% `! k* p8 d8 e
            //以后的 <<6和>>6都是FreeType2中的数据和我们使用的数据的转换 8 }, K' x# m3 O  w$ Z$ r7 y1 S
7 M( @# I3 Y) [2 c
            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )$ G# H- h, f1 d; @2 c7 m
3 X! K! G9 z% x- o) U* I
                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );6 \/ ^- N: j( H# K7 I

# v7 J- f7 V; R/ d6 n            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )% l2 c0 g, f* u

8 i! ]9 l5 }! k& Y3 ?                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;
' D$ t  D8 D9 G* e9 b
9 v2 R+ {, _1 ~7 ]7 I  4 _. S7 W/ k( F8 r& x
; G/ C/ o; i; W) ]
            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)
' T: }9 a- b. ~* l: F) {7 i1 L% Q  H4 Q" w) x( D: T
                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
5 A6 ]- t4 g! r$ V6 Z) l9 |; H
5 c% d; z5 B* n! O7 ]        }
* s! u5 A: p0 E/ U5 G) t, D" M: f2 X& |# }! J
  " g8 g6 _- n# u# c) Q2 w

) c7 [: C" ~  D4 I  
# N+ g2 f3 d, w1 Z! G# Q" ?
3 b2 }7 [- @/ v) f. s( F, K        //下面的for是找100个汉字,找出最高和最宽和最大空隙作参考。姑且认为最的汉字就在这一百个里了。 ( D* \0 l' y& |* H+ p

, g8 x2 y7 s  M. c        for( i = 20643, l = 0, m = 0, n = 0; i < 20743; i++ )
8 X" R( a" u+ }' b! t. l% l
7 T& R: W% t; `" Z  P) b4 |        {3 S! Z0 [( O2 o
) x4 w0 c& D$ N
            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );
- L' X! [) G# h  O1 @  E& g, a/ o5 b. |8 [$ e7 Z
  
( n- b' U. ^' K+ C, i8 f8 q+ g
3 R! J8 B' A  o" |. j+ {; c            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )
8 q; C: B4 Y5 D4 v# c1 D3 Y7 ^4 B% A* B* O) R% |
                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );
: l6 ?( o" a2 g; ~1 n  c
# Q/ m( `1 M( m; V9 O            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )
8 T9 O3 w+ a3 {8 X* y7 x
$ r; N9 [% U: h6 P- J                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;% r9 V! L8 I( T- s3 u% Z

  y% H! X. e6 @9 K# M) v0 A& d  - x/ p& Q% V& f0 T+ R7 {, J8 D
. ]1 `9 u2 m* G; P
            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)
2 T+ B+ B1 r' P
9 ~' w8 m& ^: A/ u; Q" H# p" O                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );) ]1 S0 I8 b1 B; T6 _. g  B" `

' O0 `$ Z; a! M9 V  
) v* X* ~1 _/ L
4 h7 B* U7 M( {& V5 x/ i                        
8 p  R7 u5 I; G" ?. ]9 q6 i% T9 j) K9 a3 D: m
            if( (mTTFMsg->face->glyph->advance.x ) + ( mTTFMsg->face->glyph->metrics.horiBearingX ) > mTTFMsg->max.width)
: w! K' B2 j1 ~* P1 O# [# w3 R2 o
' G0 F/ W( s) n) C                mTTFMsg->max.width = (mTTFMsg->face->glyph->advance.x  ) + ( mTTFMsg->face->glyph->metrics.horiBearingX );) y+ \0 p& X9 o/ v6 N) G7 C  {

3 s" X$ \8 w4 U0 P2 J        }
) T4 }, q" q+ v; l
8 K3 x% d6 U  ]  
& ]  ]0 T2 m7 ]4 \8 k) z. ~4 e8 ]: D# e! F8 j
                //下面几行行不需要了 我们要512*512' v4 A! j% t  n' z$ ?' U$ Q$ W' p+ d1 x+ Q
" R6 j3 m( d! X1 Q) @0 l; _
                size_t tex_side=512;//就是这个了 512: C, x# ]+ I2 ]# q, {2 R! q

3 C' b: M5 B0 N0 @9 ~# g        //定义数据宽度 因为是32位的位图 四个char为一个像素,为什么要位这么大呢,难道不能用8位的么,我尝试着改来着,不过改了之后就不透明了。望高手看看能不能改。 6 i3 G' O% a5 s. z3 A/ f8 Z, i
; T: H  Z4 g- m  i& H/ {# S
                size_t data_width = tex_side * 4;
" D* u6 @8 Y" C1 H
- ~! }' P# h9 D5 C* u  
( Z& W7 l/ O* w2 w, R* [  ~$ ]( N- L3 W
                LogManager::getSingleton().logMessage("Font " + mName + "using texture size " +
/ g9 ]1 B' G- Q( g8 L7 W/ C: d: T  b! m& N" p
                        StringConverter::toString(tex_side) + "x" + StringConverter::toString(tex_side));   s. [/ G8 o2 f& ~! b) b
  \3 k$ E3 R$ V% h3 L
  
0 _# P+ ~$ }* |# [7 U) |7 N' S' M. J8 y  m; |4 V! N9 W! R8 L
        uchar* imageData = new uchar[tex_side * tex_side * 4];//设置一个空间用来保存位图 + h# A5 U; T, a: J

0 V% G/ a, b. ?( `+ V                // Reset content: m2 p" r0 u. i9 B* y# M. U

9 |( e$ q+ i8 J                memset(imageData, 0, tex_side * tex_side * 4);//清零 1 C( `2 f/ l) w% K+ k7 @( c
# z5 L% ]7 O: d. v
  5 r2 y+ [7 ?& X5 P

$ w( c5 t3 z5 r        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )//遍历每个字, - S1 I0 H; b: C  b: i% c
! y$ [2 G0 v: {3 L. O/ [
        {/ Y, f7 j( }! E- f+ _

8 T  t: d  G) |/ ]                        4 \3 s+ V: L3 w5 I: h$ B
/ Y3 u8 z9 r' M
            FT_Error ftResult;
9 l' Y+ `0 j  ~3 e0 J. I
- P4 y" k0 t! _6 |  
2 \! Z2 k" D4 [4 j. l" ]$ t) j5 {9 C: N6 r9 ^. [1 p
            // Load & render glyph
$ r9 A$ v6 L- J2 `( Z/ s) k* [, d3 T  Q  e" o. D# ~
            ftResult = FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );//读取字体 2 o: E- z6 ?+ A2 m, i2 ?& o% A
& c3 ~% J) T6 c2 [" ^
            if (ftResult)+ H) Q4 M1 u8 h+ @1 S, g# D, P
- U; C: z- N+ h1 F( T9 X
            {
- \+ N3 A  |+ C; X  z: q- ~# F6 K+ d9 V1 K7 T# s$ A
                // problem loading this glyph, continue " F! z+ M# f5 O8 k
8 Q/ H  M# y, m  e& N- ?5 _& b
                LogManager::getSingleton().logMessage("Info: cannot load character " +8 ~* ?, r2 t- Z) q; q2 }$ j
) r6 h# B- o& d" l" S6 a) p$ V7 [
                    StringConverter::toString(i) + " in font " + mName);
" S2 r5 d- l* d6 B& a0 C( O% i9 J; f  ^
                continue;//如果错误跳过
9 L3 D, K( U6 O% x: C3 d6 y. q1 f6 |# S) b
            }8 A! ~9 t! ^2 |: @  w

* ?* L1 C6 ]8 }5 {  7 T  E8 P( V0 Z% h
: |" n( d" }9 E8 V; u0 i' o: v
                        // 应该是字宽
  E8 Q. H9 p9 \% R
( J/ U" h9 ~2 U- d  x! m! H                        FT_Int advance = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );' t  E: @0 W& L5 T
$ e# d) G; j: H6 Y0 w
                        2 E* u; B/ P/ o! @- E% Z/ Y+ w7 ?1 t  x

' @& S7 Y: C5 B% V8 J9 g4 D8 H                        // 得到FreeType2的位图
3 @8 ~  r6 d- s1 F- B- K+ M" Q9 N7 F2 p' L" x* X- p
            unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;. z, n$ d5 J9 U$ v, i
3 \( u. }( C  [+ [8 r" J
  % J& x" E3 M- B

% q0 m4 W9 G" Q+ J: @            if (!buffer)
. _' z0 r3 x* J/ ]+ K9 E
9 b  C3 C9 _; ]            {4 F( `+ K. S' q, d8 t" E# y
: ?! m, G5 s7 D5 P) c
                // Yuck, FT didn't detect this but generated a null pointer!
' {0 x7 w) y7 g, B
2 U2 @$ h2 S. ~# T                LogManager::getSingleton().logMessage("Info: Freetype returned null for character " +  T8 Q* W5 K& O" `0 b1 d* C, F
+ r; s- p7 Z% t9 L
                    StringConverter::toString(i) + " in font " + mName);# d/ t$ J5 ^- J
' y, D( |! A) f2 a( C  g6 a; @
                continue;//如果得不到跳过
/ }" Y; {5 ~8 t% R0 @% e
2 f; ]& n* u$ G& q  v" c            }' x: g& Y# F) Q3 b+ N7 |/ e+ M) S

9 r* a4 J% P# E, I4 `  i. R# ?2 B  
  A) o# g/ \9 u9 S# d5 C% H- I" h3 o- B/ o! l9 x+ D9 _& Q* o
                        // 得到y的空隙 (最大空-空-本字空)就是说空出这些字底部就平了 $ Z2 P% ^0 G9 z) o; s, D% L

! z, w. p1 l) y            int y_bearnig = ( max_bear >> 6 ) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );
+ w- u2 w. S" O, L% p$ G: G% p# p. \) N; [3 E0 L! z# j3 b, p9 P1 c: w' p  A
                        
! c9 H5 a3 C, {( P. m
$ Q2 [# h  g. G9 _+ c+ p( o            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )
6 d* U+ s5 x' ^" A8 M0 _, `/ Z4 ~- e) J
            {
! P. m" o& q( b9 r0 `8 |$ }4 r: i2 |9 v2 g4 Q
                                int row = j + m + y_bearnig;//相对行+本字在位图的总行+空隙
0 t) h% Z2 e$ [/ Q0 c1 D" U' s( c* F& M3 \
                int col = l;//列
5 Y# K, a: R: h# P, ]# ]! U3 d# Q1 o" x; k/ C9 V8 i
                uchar* pDest = &imageData[(row * data_width) + l * 4];//找起点   ' w8 S* J8 n1 @2 G

3 ^# r" A9 I+ f8 |7 x4 K, ~                for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//画图
. ~( T! g0 s& T# A6 ?- b. q1 W* ^
                {0 c5 K3 ~$ h7 L* Z( \- w

  \5 b, v- d( y7 X2 U! |                    if (mAntialiasColour)//看不大懂,难道是灰色字体? 1 Z8 \8 v7 L8 H0 m
5 R; p. F& V2 H& M
                    {
$ U4 R) |3 u+ {) W3 P5 J! ?1 o- T( w7 \, Q
                        // Use the same greyscale pixel for all components RGBA
; x+ f, p) |2 b  k5 U( B8 d! N1 a- ~; ]" L# i& z9 ~
                        *pDest++= *buffer;' n$ F& j1 v5 C4 v

  Q8 y& B8 {. j# j* n                            *pDest++= *buffer;
  o5 K- s% S9 n, i# O. o8 h
0 \0 r  q" h4 O; m0 y                            *pDest++= *buffer;
8 ^' z" h6 `# D. q' x
+ ~. ]% s- j( f: _9 p& L/ U) ^/ W                    }
4 v! n2 D8 r/ Z9 e8 R  p) L# ~* O6 T( \1 ]) i. r$ J3 G! n
                    else
* R) |9 w# E! Z( ~% m+ ?, o6 j
4 y& v/ G+ J& m" j5 A/ {- t) ^                    {
5 g% L1 c* Y! I, J4 S* u4 @# @7 n
/ _9 q% J4 k. D6 M                        // Clamp colour to full white or off & ?( g/ [5 v/ Z$ E

7 _0 ^  o  V# K1 L. a# p                        if (*buffer > 0)+ I  i* i4 c. T5 `6 s' R& @9 g

0 a- {# g& Y. N& W0 ]) {5 X2 A                        {
: I9 S) g4 Z3 L' s
6 Y0 L+ D5 I4 r# l  O! }                            *pDest++= 0xFF;, w3 ]7 w! ~( |7 L5 l# t3 L2 ~4 a
  S: d' l" b- y& k/ s6 I1 b
                            *pDest++= 0xFF;1 @7 u; t$ {5 t+ Z( a
0 _8 W4 j# t  \/ w5 _
                            *pDest++= 0xFF;2 ]- u" Z! K: j1 x2 O0 a, m
% O5 d2 j5 S6 H$ ]/ \9 t1 f
                        }
* }- u! q, g( a4 B2 A8 I
7 G2 d5 {) h4 i                        else + o7 Y4 q) _& T# `

# x4 J- d3 u* s: N                        {
3 o2 R- f1 ]/ c" |. w7 `1 {
3 c9 X  Q$ G- c0 d/ @                            *pDest++= 0;
  c8 M* G4 n6 y! e! D. O% P* {% ~" n. r# q
                            *pDest++= 0;  i4 L5 l3 K/ d# C: ~" W
* a; \2 q7 m: z1 e
                            *pDest++= 0;6 m' f+ b7 E% {; x+ d/ J% N% l
1 K* A3 L% P* d8 I8 x
                        }$ _! U" k3 X! w5 j
' U' J& \2 E* o- H/ Y, ?4 r
                    }
+ J) T) z$ L5 ?, x: x' `! \2 h
0 k1 V2 Q1 ~% r. J1 T                    // Always use the greyscale value for alpha , z9 N" |- S2 Q* X3 j
% x1 K1 T& r2 `; k( z; a
                                        6 n0 _' {3 u: X' |9 U1 p

' f& p" z! x# d% c  M                    *pDest++= *buffer++;//alpha! 我是一点不了解了为什么是这个?
' m4 p/ k# G. V' M9 y% ?$ `! [5 }  C- {
! J4 m; Z  g) L                }
/ }* B# K3 ?# R# q' a- W
! c3 \8 u  i; V            }) }; v2 f. [  E. t% h

$ w2 j9 J. ?, v3 Y  
  ?  A6 U/ d. H( Z) }& r! d
! U( q. a# d1 {& D            this->setGlyphTexCoords( i, ) m. V+ G$ W' D3 m$ @

/ q9 e; G2 ^! s( R8 G- u/ E                (Real)l / (Real)tex_side,  // u1
& s4 N, ?% K7 N# A0 [
. j% v( n. u, Y, [' P                (Real)m / (Real)tex_side,  // v1
! j$ D* [6 Y) m# l) L. c; B0 n' m2 G9 |
                (Real)( l + ( mTTFMsg->face->glyph->advance.x >> 6 ) ) / (Real)tex_side, // u2
& `! A4 x, [2 ?. }% }# Z2 y& `( t" G2 ~1 |
                (Real)( m + ( max_height >> 6 ) ) / (Real)tex_side // v27 o4 R( [  L( k+ X& l! g

, f" e6 Z$ ]) M! C1 ~                );//设置坐标 % I; r, _4 y4 ?6 u7 [% f8 [& t( W9 {9 N

' k1 Q6 {  C$ `6 I8 i! X4 }: ~  
' {  e, b+ S: m+ s; }: Z6 U" K/ Z5 h5 x1 ^0 i- r
            // Advance a column
0 `: ?1 Y4 j; {6 V! h1 d+ M3 `7 v2 E
0 A" f( |; @: W4 h6 k% j* i) H            l += (advance + mTTFMsg->char_spacer);3 R; {2 i" R; V2 N; U
1 r0 s1 A$ w6 i# w. ]- l
                        //l+= 本字宽+字空
$ f8 |6 P7 Y8 P. L
: U9 [3 H& @# j* k2 s; |  / U5 D2 d) b9 Q) r7 R

" s, ~- D2 h# F5 |% \$ F$ ^            // If at end of row ; O) Z" }* s2 }+ H% t

) S7 m! C  H: Z; T) {                        //如果到头容不下一个字 4 T* K% T, [/ c, K4 I
- K! o$ U: |9 w" n2 b; E: ]3 z
            if( tex_side - 1 < l + ( advance ) )+ ~; [* ^4 t- k! }2 X, O

' M$ k! W6 }4 L' }" J  M            {
  t7 s* \$ w- Y# u7 |, @% e
2 Y: l# ^. |4 n3 [5 h! V/ p; R                m += ( max_height >> 6 ) + mTTFMsg->char_spacer;
  L0 n) B+ O0 T( ]: W5 X8 A* o( r4 s9 }0 M; ^6 m
                l = n = 0;
, S- L5 T6 p* d1 I8 P, m8 p. X2 C6 E% S
            }
; R' W) U% p" s0 F/ M3 W# _  X5 x$ _8 K1 L+ D
  
7 L! ]% X/ f2 H3 m7 k% i+ V- ]) d" h! s
        }
6 b1 [. b" L% h
5 w* }/ T# u$ `) d* X                // 把信息存到我们的mTTFMsg中 >_<
* N! w$ b# K: s; }; P3 W& i# v. Q% A1 ]2 y1 |  e
                if(l)
5 z$ S) }0 D$ g! N# W2 G% d
/ s, q$ a. ]5 x2 a& `8 f/ T, B0 r1 B1 v- [                        mTTFMsg->point.second = m + ( max_height >> 6 ) + mTTFMsg->char_spacer;0 p) N5 K% \3 E) l- b% v0 z
" q& F# P7 P8 P! r' R4 n
                else
. Y& M/ s; x& t2 Q
0 Y4 M4 x# A0 }+ N/ s( z6 j6 M2 F                        mTTFMsg->point.second = m;
- Y) A8 u8 [$ Z0 Q" ^; O
6 ~$ F* \, g6 {) ?, ?# x+ D$ D  }* x8 N  - p9 F* p  W3 `4 j2 t

" y1 ]2 M5 A5 y  j. y) g/ D                mTTFMsg->point.first = 0;//另起一行
) o2 b. m% X: W0 a1 @
2 ^( L; i; C! n7 o( _0 h3 m2 V. R* ~  
$ Q$ {- L8 N: x7 c
( G6 Y0 Z6 r1 {* g% R                //下面是保存几个最大。 + {1 O' T5 D3 P3 Q+ s1 H

3 ^4 o, D. z: j( i4 X+ n                mTTFMsg->max.height = max_height >> 6;
/ f. c& e! h7 ~# g) i
, o4 ^9 K5 y, [) N- h4 {                mTTFMsg->max.bear=max_bear >> 6;
* b, D' n' `. T! ~, a8 f1 m& d) g, U9 z9 o7 N7 _: e" K
                mTTFMsg->max.width=max_width;9 s2 n9 y: _- J9 S

) T/ e& _2 u3 v' Z  # D& E+ q& D" s4 V
& A2 D" l3 h5 h. [
                mTTFMsg->imgchunk.allocate( tex_side * tex_side * 4,imageData);4 H* A' X  o+ A7 z5 g4 Z

9 J1 ^7 b, u7 v  N8 S                . B/ F5 c: C+ d$ N! z: \1 N7 A7 k
/ a. C6 l/ P  p
                //不知道为什么要设置img这个中间变量,似乎可以直接从chunk创建贴图 8 N# _( K2 z% H7 y1 p, x

- Q9 P- e/ j# {        //--Image img;
; D3 P2 F& _  ?/ E; o4 ^& K$ u9 K# e% m, R
                //img.loadRawData( imgchunk, tex_side, tex_side, PF_A8R8G8B8 );
* j9 e$ U) P3 v; a" l
+ F. t6 c& x* `  }) Z+ {! m/ l& W  + b7 {2 E- n6 z* b4 F0 n( B5 J
7 a/ w9 y; M- X- d- x5 V  u+ d
                //贴图名
1 s6 F& \# G  W6 ~. g4 }+ t9 i1 l- T1 o  `8 S; f' e/ \
        String texName = mName + "Texture";
% V( m- y5 s; h4 V
7 X5 B, t( S+ f                // Load texture with no mipmaps 0 \* w2 z  \7 M

% G4 }3 j' Q7 n+ L  G$ _. o* ?        // 把从img创建位图改成直接从chunk创建贴图 # q  G. U/ Y1 I$ I9 |/ ~% F) n! O
: y# I% H& b% p# L5 g
                //TextureManager::getSingleton().loadImage( texName , img, TEX_TYPE_2D, 0  );
$ F7 {! ]( l; M# g, z* E9 x7 J
4 @4 M4 @% p5 q/ i/ u                TextureManager::getSingleton().loadRawData ( texName , mTTFMsg->imgchunk,tex_side, tex_side,PF_A8R8G8B8, TEX_TYPE_2D, 0  );( N* i9 f+ e8 c) V7 a

! ^6 W3 ^* m8 h( m7 W* P) H! i" p. }) C        TextureUnitState* t = mpMaterial->getTechnique(0)->getPass(0)->createTextureUnitState( texName );0 L( r' a; C6 {* |

( D/ g  P. L4 @9 Q                // Allow min/mag filter, but no mip
* j: {. i" O# w. J+ J( a& ~6 p' e. x0 K7 Q! W
                t->setTextureFiltering(FO_LINEAR, FO_LINEAR, FO_NONE);! _! |& T! L/ @* f/ f% i

+ `4 P7 k- E/ O2 O) f4 ~( s        // SDDatachunk will delete imageData
7 B0 o! U8 b+ B  }: @% Z+ }3 {9 n- a, s  F$ R2 F
        
  ~& J6 f4 }$ }! X5 G
" o% y) u" H5 i, Q, W! j( A3 b    }
! W$ z$ `: S1 U- d6 N( Y7 C7 [
" u# o: J. z7 E: M1 X        你应该对照一下以前的函数,改了很多的。
1 Z: w8 e* W" M
9 e1 K; M( T; b5 {, @5 c  : d! V, m0 G( z9 Q% q/ }
9 g' }3 @2 \5 n6 b1 ~, G
  " ]4 `1 t- M' |  y  |& L
1 M) G0 O/ w* d
(3)
" u* g+ |4 y- T% f& H' f" Z4 D3 }1 X) S9 M
        然后最重要的是动态的申请和画字。
2 A, K2 r+ ]% ]% ^/ Y9 ^. [5 C- P% U
        首先最重要的是我们要一个方法得到汉字的unicode码,我们用到了unicodeMap数组,提供了区位码到unicode码的转换工作,等一下提供这个表给你,好不容易从网上找到的阿,可惜这个表没有中文标点的对应,如果希望支持中文标点,就要努力找到unicode码并加进这个表了。这个表是这样的 char c[3]="邸";unicodeMap[94*(c[0]-0xa0-1)+c[1]-0xa0-1];就得到邸的unicode码,不知道为什么没有5165~5169的unicode码,是轮空么?
: d. T* b) _" z. m, E- R" h* |( S% ]/ ]7 I5 ]( Y
        
7 P" J/ |$ p) D% C0 M3 m
) W+ c+ c1 I7 c7 V) y. \* F8 Q        申请渲染(字)
5 D- s. P# E: z/ q4 P8 \$ d* V& [" t9 K
        {$ M$ x, T' w; k+ o2 t1 h

' N. S/ T$ T% H: T8 u  @$ a, @5 i                if(有这个字). J# K/ x. Q. p$ D7 P$ u8 s
1 W$ m* e, w3 ?/ r2 o5 X
                        返回位置   |$ z5 q/ @/ q

. ^/ G! w3 H5 S( W8 Y; h# l5 E                else' m: f1 v4 C: m5 X/ r( U
( r, [" K; C' R( ?6 X! Q" g
                {# |) Z9 `. G9 \1 H) E! ]0 x
- w4 @  g7 N) K0 u3 d% E
                        if(有空间)
0 Y5 ~3 e- h# H+ M' B  o) d. @, X: w% S/ h, p
                                画字
; Q" q+ t% n+ W0 \" P2 s% x6 x. J8 @0 }9 S4 K8 I8 x; S0 o/ o& j9 X
                        else
. [  d$ j4 f/ I$ h8 y) E$ j6 K/ H
                            找不用的字//找不到就出错,没地方画了 % Q  [/ M1 B; f+ K0 ?
6 F- Q3 V. |/ O; |9 {* i1 M
                                删除 在这个位置上画字 + e* |! K' |) S+ W
; v0 ~3 }8 c6 L) }2 ?3 _4 |, v
                返回位置
8 |# B1 q) Z: u
; b4 F( [) K( @- A9 W                }
/ B4 d. ^6 d) i% U2 }) p1 P! f4 \- d: b1 v, {  d+ \
        }
6 n# [* S/ v. p# ~- e1 _. o+ @8 q" m! ]( u0 k/ z
        上面很直观把,大体就这个意思了,申请渲染的函数是inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )  const。去掉const改一改。得到
* R8 H# }7 Q, o0 N0 _- E/ J. I6 }* G0 e6 [9 |! `- X+ n( D& m* H8 @
        a.申请渲染 . ~$ H3 }1 r  K3 m

  @0 O' H7 G! t  h4 }0 h3 l. m% ]4 l        inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )         8 v* a6 q! e+ |( |# P; N7 |
- _0 x- R& M( D: j
        {9 H# k2 d# n# C/ {5 R9 _5 e

* u: f# @9 |7 _- n0 {                unsigned long idx = OGRE_GLYPH_INDEX(id);
% J5 G4 H1 g" X* V) F# a7 S* F
. L0 z* }6 {" _8 b" ^' Q: v8 s& z                if(this->mType==FT_TRUETYPE)//ttf?  _* L% N$ `1 c2 a
" U% {/ x4 \; d6 h
                if(id>=161&&idx<OGRE_NUM_GLYPHS)//汉字?
6 `1 c- Y' \( b. V! s5 g+ l; @8 c/ @* k; k3 b
                        if(!mTexCoords_v2[ idx ])//没有?/ F) |8 U4 s% |% S8 {4 N4 `/ L

, Z: p- y  _' J. V' c$ Z                                setChar(id);//画字去 & I5 j+ C+ q5 b+ }( Q

/ G* Z  n5 O! g9 {" v             , p/ V) l$ k0 j5 b7 _! E1 u7 T
1 H, ]4 H3 f; ~$ X' t3 Q
            u1 = mTexCoords_u1[ idx ];5 g5 N; J$ W: |4 H1 x6 h! O
# n  V9 L2 w& K1 I; x6 l7 a
            v1 = mTexCoords_v1[ idx ];
! ^. k/ _- N( P# T" L# l# l! b1 K4 ~! s3 U
            u2 = mTexCoords_u2[ idx ];. C# P9 {- I5 G4 f; v  `
9 F0 Y) N6 F" A4 Y" J
            v2 = mTexCoords_v2[ idx ];3 F$ C& B% L- b' F# D1 m+ ?9 T) I
; e/ J0 j. |) O6 k7 h
        }
& e+ P6 c- b0 S: }! \6 I8 ]
# X. u& n: L8 }( T6 f& g        b.画字等
1 T) H. P+ E# X! @7 _3 {
5 B# ]" L6 g6 y( u5 g) @        bool Font::setChar(unsigned long dwChar)
( u- q, r0 L6 k- j: p+ D6 e: J
        {
/ ^1 ?7 f1 W5 N3 A9 @" C
  Z' U! L, K% W4 d; {                int j,k;
/ I  T1 P% O- Z% h8 r
9 W. a0 D. b# k                uchar* pDest;//操作数据的指针
- F% y' O1 m( B8 ]5 Y0 l  k3 [$ @" U, A# _& o" V) `" F
                mProportion=0.8;//不知为什么,总觉得中文都太扁平了,所以设置这个参数,在《让OGRE支持中文》中创造的参数
6 L9 u& [1 `7 b; c, a( i
6 e# l; k' X% f. p/ @# s                Image::Rect  rect;//画字的位置 2 b& ?) ?4 @0 [
. r& @0 W9 j& m* B+ f3 c
                if(!mTTFMsg->getRect(rect)/*回头看看这个函数吧*/)//如果得不到空位置 8 z( B) x2 @( j% K& e- i; z

  I& Y' T1 c  h+ d4 w0 f  V                {% L9 q. h" X9 A8 M# Q! ~, G  q

' d' M2 ]8 y) P4 E$ |! S5 Y                        for(int i=161;i<OGRE_NUM_GLYPHS;++i)//寻找不用的字 # F# n. `, j. V; @$ K
" y0 A& Y" d6 G
                        {& a- e" s! g9 b

; Y! D% A0 J1 t. z                                if(!mUsing&&mTexCoords_v2)
- _! C5 d, u* N3 N( l
2 ]( s* M' S; a0 _0 x5 T                                {
0 s& m' P' Z, Q$ w9 R+ x1 X
# _1 k$ O8 P$ }4 x! Z, {                                        // 得到坐标
6 z7 Q* S# e0 d
. x5 ^& F0 i9 Z5 d7 a! e3 {                                        rect.left=mTexCoords_u1*512;( w. |/ P: r: T& ]; Z
- n; V8 [, L+ ?: E
                                        rect.top=mTexCoords_v1*512;
& Q$ n/ _9 |9 T+ c1 {) G
* T4 T8 V9 g6 c/ Y" u+ ~/ F& d* S2 ~, a                                        rect.bottom=mTTFMsg->max.height;3 `, e; Z$ L) w
( r2 C3 A9 f# x  f% B. y, Q
                                        rect.right=mTTFMsg->max.width;
& @$ @& E2 L2 [
! g3 P: N4 y; |; X! {- @  1 r8 D$ x* g* ]) [

1 K/ ~9 Y1 ~! F$ N. ~) ~' W                                        - R5 @# @5 n) }" ?
) l3 r( A" B' q5 E
                                       
" d# @. p) z2 b
# }( M: Y; K8 {                                0 {0 E3 M" G9 o1 r

' v( F5 N/ C3 b6 g* W                                        //擦除(这段代码没有试验过,等做完输入的类在检查吧)
5 z9 K6 w; A( a; j. k+ A, i$ Z& e% i$ I. U1 f' ]7 G# e% t" V
                                        for( j = 0; j < mTTFMsg->max.height; j++ )" ~, Z% t: T# k9 b% F. L5 L
7 H: {$ l$ p+ f* |% H# l8 T
                                        {
- U# b- s, ~' j  r* Q5 V; m5 e
8 J% x/ \% C1 }3 Q) H5 w                                                pDest=mTTFMsg->imgchunk.getPtr();
: [4 M( C6 n5 i6 i9 w: j' Y1 u8 g' F; v" D) o
                                                pDest+=((j + rect.top)* (512*4)) + rect.left * 4;
6 o8 l; @3 T' p7 \4 K6 m; |- W! ~4 ]$ G" x1 q8 ~( `
                                                memset(pDest,0,mTTFMsg->max.width*4);
& s  R1 s& G  P2 n3 l( b- v8 S; @/ L+ C. i* k8 h8 k
                                        }* ]5 S3 U' Z( E# T9 ^
. m3 O9 n( l/ @( `
                                        mTexCoords_u1=mTexCoords_v1=mTexCoords_u2=mTexCoords_v2=0;
# B# }8 D) T% e+ ^
0 O* i8 N$ u9 o, T6 D  
$ ?' U9 Y' y2 z3 r/ l% B: g. c* S% H9 t' [& [. P$ k
                                        break;
% `- F. ]: S" ?7 ~% F5 O) n
4 q. e0 e' _0 f5 b4 |0 j                                }
5 t" [% J' s# X# g2 {
1 {1 v; L1 f, O9 I; V                        }
/ J. W% f& r* E5 x3 v* Q5 Y( ~3 v+ L) }; Y
                        
' {5 R' a2 q4 ]( k2 Z% P! v
+ Z! t# l2 ]( s- d1 T2 R                        if(rect.top==-1)//啊啊啊啊啊啊啊啊啊,贴图竟然都用完了,没办法了,出错了
0 j$ G# g) ], \& R3 _2 x; F8 W! m# E! @  F
                        {/ A$ }& _% I  q4 B3 @4 H7 O

9 b4 J+ |7 b' U, H$ ?& m2 \, d+ A7 x                                LogManager::getSingleton().logMessage("你太贪婪了,用的汉字太多了,这是对你的惩罚."); ' |; L: M3 V+ l: |2 A

  c/ `! _7 J0 C0 o" G                                return false;
0 w9 l# C9 `! [' P3 S" F5 q" q$ J( `: r; Q! N1 i
                        }
' s5 J, E) m; I
: ^' u3 M0 H% N' u3 Y& }        
! q& u5 a, Q$ r
" r2 l$ H6 n" u9 J: C* k9 C3 G& g                }9 V. b( R- H' D
3 _0 ?' }0 a% C, N1 a7 a7 J6 M7 h
                        
9 j& P8 o2 }! ]; `1 R& z1 ]7 h* B9 g, Z4 h; H7 u1 P0 ?
               
& o2 N- A* C: s0 f$ ~2 j* T9 o4 ^
8 \  s9 `5 l# ^; h8 r                  //以下画字的都是招葫芦画瓢的, # Z- U# C7 Q. S6 [& b+ x: @- w

+ W. z9 u. Z% R/ {" j8 }                  FILE *fo_def = stdout;
6 X0 f  q, i7 [8 Z' `" @/ W6 m& H) ?0 }( F& t0 O  Y
                 FT_Error ftResult;* g2 S7 A) d6 P$ w6 J! X8 j9 _

1 u9 U2 U! a/ m+ v$ Q  ( v/ i$ f- U: K& A( U

# l% x% j1 U5 v4 F" z% @( t6 U6 |5 \            // Load & render glyph
  W( L6 e9 s+ ^4 D% C7 M/ ]
* |) z3 y" B3 X. |  Q& V                  $ u# A: L& m' l$ l3 h. d! U/ H
8 ]) |3 j# w0 \2 J" n7 ?+ q1 s5 n
            ftResult = FT_Load_Char( mTTFMsg->face, unicodeMap[dwChar-161], FT_LOAD_RENDER );//读取字体 5 U( t1 r3 g* J; O! D
. _3 D1 ^8 ~  G# N/ i
            if (ftResult)
6 ]  G" Y# n: y  X# I
. u+ n1 m/ ~4 c            {
; \  f- K% O. ?! c5 M' F$ B9 ]9 f! v' V1 @! G. B! W! B; ]/ n4 L
                // problem loading this glyph, continue
9 @& M1 q" g5 X/ ~/ Y9 _. M& O; P; }7 e" S+ O( ]; `/ A
                LogManager::getSingleton().logMessage("Info: cannot load character " +0 j" Z2 q9 u5 f, V  g& V

- x' l! V5 v# |( |                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);- R6 t# n  Z2 U; f9 Q* m

+ x3 }5 T: a2 S$ F                return false;//如果错误跳过 ; ?* T" d5 I7 m4 S

' G% d: ^# G1 g' Q" T9 f' \; u            }
! V5 m3 Y  M, Y5 h: Z, f( @- ~6 l* W/ u
, I) t* s) C5 a1 X+ `  F  
/ M1 y+ z7 e$ [9 N7 y
$ i+ O" F7 L* f( C% `6 v& j          unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;% ^- _  K8 z" v6 P) J0 Q8 P
, ?# b; `- Y, z2 R2 Z4 f4 \3 W1 f. @
                  // 位图指针 / q( k' Q% n+ q1 s

$ `' N' K1 N7 g$ [8 ~            if (!buffer)
3 t- w5 R; e8 b" \# @  B" u7 k% k/ U8 j5 [4 W
            {
4 L1 d* s! ^$ v& L6 Y
; b$ G. _8 p7 d4 ?                // Yuck, FT didn't detect this but generated a null pointer!
% _4 q8 ^( ]# @+ n8 a2 r/ x6 h2 ]6 \& a8 c
                LogManager::getSingleton().logMessage("Info: 1111Freetype returned null for character " +1 v0 T* P' ^1 J# U  m

$ g3 @  q( g8 o3 N* |3 B                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);
- l! ~- N& Z' m3 L' m9 h. X6 E3 {! C6 E4 |; Z
                return false;//如果得不到跳过
. Z6 C* R; D: P: z9 x0 \8 y: o$ `7 v  \# }6 T' o
            }
: R4 u/ r5 o$ |; B1 E
$ X  `( w3 L4 X7 O2 v) C% V  1 G2 A. R# P5 p

* C$ ?7 U9 M. I$ m/ f4 Y                         int y_bearnig = ( mTTFMsg->max.bear) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );' S. t) S, Y( `
9 i5 i5 A4 L5 l- y1 @
      
8 C2 l7 h  O8 {9 r
6 r1 z+ |7 E4 g* h0 ?1 K. O                        
' ^3 F7 O7 `) Q  d8 @: \
+ N  `+ j8 q# Q: @4 V& Q            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )
' v! p. z1 |1 z5 p, P5 W# |. I1 X4 Y1 n9 Y) N! c
            {" J3 I5 E0 s& D' [( E5 ^% `( J
" z  `5 \, b/ Y
                int row = j + rect.top+y_bearnig;
% n+ H6 S# r, O2 o. R- j" k
5 f+ N9 I, ^4 J% M7 C                int col = rect.left;//列
- B: e* o# x# q0 X4 x7 v" E  [) V; c( Z$ @
                                pDest=mTTFMsg->imgchunk.getPtr();8 V: `) y% a5 D! Z) G. e; n7 {5 A
  n2 c- W' W- [8 ]
  6 P5 ]) u: B9 i( k, c) J

; K0 ]0 a$ Y& d* K  @6 _) p                        
- t# p4 ]% D* A7 q* z, D4 V) b" J5 u( }# W$ {. x
                                pDest+=(row * (512*4)) + col * 4;
( H' Q& M& Y7 u  Q
. M, l" d2 S) k& E" ~               for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//每行的点
5 ^8 _9 [( T3 V, ~5 H, y! Y8 U  f4 @; ^5 x
                {
+ X( o! x" \1 ?. A7 {6 y; Y! A6 I( e) o
                    if (mAntialiasColour)" u, s, q- J9 c! R

9 q9 T; ~% Z3 B/ f. d                    {4 @( U3 U0 d4 F+ a6 \
4 T. n1 u( p4 {) T5 b
                        // Use the same greyscale pixel for all components RGBA
3 I3 l% Y; r) R% I
( Q* c8 {2 `0 V0 l; k4 S4 f                                                        *pDest++= *buffer;
/ n9 [( \" Q+ n3 A- Y: i- Y8 [: R* J+ i8 f) b
                            *pDest++= *buffer;
) _. X  W. G; n# ^" {8 a, z7 U4 b( W; J* [
                            *pDest++= *buffer;
. w6 x% ]1 K- K: o, u+ S0 A6 d! k* \1 i. k+ `& P  G+ D' T7 g: k3 t* e
                    }' L3 x5 L! o& m& N& p. Y

; Q: h9 {9 C; y* }% ]                    else
% o+ B" r, a4 k" v( Z9 n" Z& N6 {2 {3 D' n8 U- X+ \. B+ x, ^2 D. o
                    {6 h1 n1 L, t- I7 t8 _
' A% |: H! M! O- T) ]8 f) g( H
                        // Clamp colour to full white or off
! Y# q5 s: X- E1 Y
& m6 d- B' j6 ~: N" ]4 Z                        if (*buffer > 0); n5 }, g  [2 W% G0 l- m* G% _+ Z

& W9 M6 {2 S. F                        {4 \# V0 \! m; e1 R3 ~( W8 w) G+ w$ n
/ O9 E' y$ {" F1 u% j: |
                            *pDest++= 0xFF;
( |" r8 C: g3 u" b# h/ h- \: g% [0 N  m
                            *pDest++= 0xFF;
8 |4 a- k1 W  o6 h8 g& H, ]
6 x1 |9 i$ n/ Z5 s                            *pDest++= 0xFF;
: a: F6 o0 m0 P# f% z
" O1 f5 Q" k0 j  W                        }& R0 W7 [! `3 H' ]! b

9 h* k. c9 ~, ~5 F                        else
+ e. U* }5 B8 W6 L9 B, T- \2 o% q5 ^+ f0 U
                        {
+ f9 _- I0 j3 v$ n% o
! n- c1 o& M, H% c/ Z+ ^                            *pDest++= 0;9 T9 G4 n: n/ u$ Z7 F

- V/ K- U8 b& M, [7 |8 A$ l+ N! j( I                            *pDest++= 0;
9 ~! s) o2 V% l! s: U: x, `6 }; N9 ~5 {5 h
                            *pDest++= 0;8 M% m) r/ x6 K6 A8 \: ~0 L7 y# U
( U1 Q* X# J8 ~! Q
                        }
0 A- p+ @! t. s, Y  d8 `) B. w3 A- a% n! y  F3 ~
                    }
% s7 i6 X8 [" ]* L* A. M
! a2 I: ^! w. _) p+ S$ |: s                    // Always use the greyscale value for alpha 6 K7 u) v5 C. \* ?: T+ f
" Q( g+ W( i- E9 v, U
                                       
1 ]# E4 a) p' k$ B. g5 o  Q5 Z' U5 N* I. ]2 j4 A& J1 X. [
                                //      LogManager::getSingleton().logMessage(StringConverter::toString(*buffer)+"is cool");- x3 ~8 T0 \9 p$ k7 @

) V4 r$ z- H6 h5 x5 x/ ^; t9 _+ x2 w2 V+ \                    *pDest++= *buffer++;
6 W- X' M( D/ s* F) L# p0 G' S6 Q$ k7 f& I/ H0 x% Z
                }$ M6 F. ~7 x& A  j( [* z
# n& |, @2 r/ C2 c
                                " U* A3 I/ G6 {7 A+ v. i- q. I
$ F8 i" q1 W- B" a( b- i9 V( V
                        }
$ m0 L: g  u, C6 z. {, W/ ?( |6 o, w. _6 F4 M; R
                        // 设置位置   l9 I, v! ^& s: S
8 ~. K0 E' K# q  \1 k5 g; d
                        this->setGlyphTexCoords( dwChar, , _9 o  A6 T9 Q" o- l' ?. w

" g" k; n2 q* x. `                                 (Real)rect.left / 512.0f,  // u1
' }% T+ l, t$ E9 k- E8 G/ I! ^; |" b* M1 z5 P$ a
                                (Real)rect.top / 512.0f,  // v1
( K- X9 k* |$ z8 ^+ n# n- l  A" L: T. w$ `) j
                                (Real)( rect.left + (mTTFMsg->face->glyph->advance.x >> 6) ) / 512.0f, // u2
& g" @* F  X( a+ m2 C! q
! a# N  F( l" \& x+ F                                (Real)( rect.top + rect.bottom ) / 512.0f // v2
5 ^' P) p, _% D; K1 T
) \3 a: M% g# v; r( T- d, e$ k                                        );
. q# P3 e$ m2 l* {/ J+ n% R3 ]9 @* e9 d, A0 U
                mTTFMsg->dirty=true;//贴图需要更新 / T7 j  f* @& J4 ^+ W. }- h3 M

* |- t) t6 }6 Y" ?: Q3 D                return true;
0 N: _% V7 p. O1 g0 l. t5 K# V# a$ F) T8 {$ K, z% G3 _, E
        }  O" p+ D$ Y8 V1 d+ B1 z, [) A
7 V/ L5 d8 ]0 d: F5 ]: v
  
& P, u1 P6 j" K8 o) Z0 B
( \/ p1 R+ f( `4 b8 p7 g# G(4) " U$ z& V. |7 O% w" b4 v3 o. A
7 i" ]: U4 @; f
        松口气吧,繁重的工作都做完了,就是更新贴图了。
; ?: @. V4 H# W% [9 E& s7 ~; g5 x, E
        Font类中~
* h4 \3 U- {$ s! e
" L% y1 G: S3 B2 H        inline void write()# \/ x5 @3 o: E% H
% I: o/ S# n# t4 c* {( `
                {5 V; Y2 f% H, c1 J2 `6 z  d6 Z
9 p- Q5 |; ~! }9 t4 ^' N1 Q
                        if(mTTFMsg->dirty)8 d7 t, y/ P* X
4 E( k. y( H6 C0 g
                        {      
- _! k' k2 P% ~' \. G8 k% m7 t4 j% u; m7 z7 d9 X
                                // 重新载入贴图,顺便说一句,类似功能的函数还有
0 _5 B' @& Y0 Z; g3 u
9 l# n  a8 l/ E                                //virtual void  blitToTexture (const Image &src, unsigned uStartX, unsigned uStartY)=0
: m( S& s: r) L) L; \
8 L; M$ ~2 H; y  O5 W                                //和virtual void  blitImage (const Image &src, const Image::Rect imgRect, const Image::Rect texRect)( e7 X4 J2 p2 v) O' ~( }
4 F/ L  C# T, R6 Q. l
                                //不过blitToTexture()在ogre-win32-v0-14-0之前没有实现,没有尝试使用。 blitImage()就算到现在也没有实现。 5 T" C+ H' ^! {) a+ U& \) J

$ v1 U" Q! o! l3 h    b, d6 v! y. n9 X6 f; [4 G/ q

8 P* ?- r0 O5 U% `2 A/ k                                TextureManager::getSingleton().unload ( mName + "Texture");0 x1 V( d+ o& v/ W. c: P% j

* N- f2 m  {1 ~6 b# p5 N                                TextureManager::getSingleton().loadRawData ( mName + "Texture" , mTTFMsg->imgchunk,512, 512,PF_A8R8G8B8, TEX_TYPE_2D, 0  );& h) [3 y* R4 p3 [3 M" h% j6 ]
$ _( o) Y' V3 }5 V
                                mTTFMsg->dirty=false;- d3 J2 O) K- x1 B8 Q" w! O

% j7 }& g/ L. y+ N& [                        }
7 L' h2 N; I" i- Y8 Q2 Q- Y5 g1 k- K
                }
+ [( K+ ?! g" D) }2 V
7 K- x  s6 Q! B0 M1 Y) f  + c7 _( z. V* \. w

/ o6 L- K2 z  {# x4 ]$ {0 G9 b4 y$ `4 x         在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。   p+ ~& Y$ ?0 e% A3 q

' x% X+ M" v0 X. S, U  ' c& N2 T4 b- R! r
! w4 Z1 U% H+ h, X
  " H2 p5 y% J8 ?1 {9 l3 l* [  H* k
; `1 p  ^! R: B4 o" n" v1 `
4.结果。
: m6 h* d5 e, ~0 _  c. M" T  l& W& u: h! U3 M
        好长阿,写了好长。虽然多是代码,但写注释也很累啊。重温了这些天的工作结果。就像上一篇一样“在OpenGL和DX9.0中成功的支持了中文,但是DX7.0中竟然出现了运行错误,具体问题还不清楚,还望各位高手指教。”。不过本来OGRE就不怎么支持DX7的,不管了吧。OpenGL中渲染的比DX9.0清晰,是我的显卡的原因么?以上的winXp+vs2003.net+艾尔沙980se通过~。。 % ~. l; q9 K& d8 d3 @. D

" ?6 D4 G" Z0 a8 X% _        顺便说两句,上次发表了拙作,没想到好多朋友和高人们找到了我。甚至联系到了一个南方的公司,说要做一个引擎支持中文的方面。但是卖完400多的火车票之后竟然因为住房问题作废了,5555,退票少了80元啊。还是自己差阿,如果再多学点可能就能要我了把~。努力吧,争取写《让OGRE支持中文》三部曲。
( x: ?, q6 [  Q' U. }! U3 @6 [% D  \5 G: k! |4 E5 R
        下一篇应该是《可以输入中文了》。
: i" f4 }; V! H0 d
. i$ i4 P0 k1 B        也可能写不出来的~~~~~~~~~~~~~~~~~~~~    ; D. C1 ~! p0 _9 `* x2 p
; z8 {% y9 V- d8 l1 g3 M* z
    相关文件
' z9 Z/ R9 n8 R4 M* m5 O) J8 T  G1 h4 d  q$ F' F
    chinese.fontdef//字体信息文件 放在资源文件加中 $ n, Z# u/ p/ M+ w5 O  o3 p! N

3 |1 D$ T5 M, {: C( _7 G6 ?+ R  W    font.png//字体图片 放在资源文件加中
, I3 J. x$ A8 F$ ]  q/ A% B# \* o. l. `1 V; H( I. K
  
9 G9 B& W  i% J  @: c4 W
. Z; F% X/ z  r5 O* Y. `9 u$ Q    OgreFont.cpp$ I. J9 d# W! _* N8 A8 m& \

0 U# b" i1 _5 J, ^) u    OgreFont.h
/ `* q+ g. B) _+ h# x# I
6 E5 t, Z; S9 D    OgreFontManager.cpp
6 K9 _3 W8 U( j1 b( Y) n9 L/ y1 H
    OgreTextAreaGuiElement.cpp8 G: Z8 \% l" u& ?$ v; V2 p
2 E. a% Q. ]( w4 {+ U: L. k9 q
    //上面文件覆盖同名文件 就可以 先备份 & x$ ]9 {3 r) m5 f( F
1 y) z: d4 c  N
   
7 y: t" i1 i" A: l% w7 N
3 A- ^0 @/ U4 T$ ^. p0 k! }   solo5.ttf//这个是一个中文ttf 我直接替换了原来的ttf3 R& K" S, [& W. U* a

9 ?* d1 W' z( v& D# ?1 `. W7 Y   unicodemap.h//这个重要,是换算unicode码的数组(文中提到) / A1 h  \0 d; b, Y4 P& x( j2 K

0 M6 Q- M+ x) ]) L$ G  & e8 H4 H3 U& d

; s4 v" `, n+ V, A# B这个是在ogre-win32-v0-14-0基础上改的(上次是ogre-win32-v0-13-1),
# {( k% l6 h7 J" n- g6 M* v) D: {. H: v8 e- a" ~* ^
请到http://sourceforge.net/projects/ogre/下载
1 j( X& }1 V: R) f4 K, H8 W9 X3 g! E. D. {4 h8 X! Z
配套档案下载:http://www.gameres.com/Articles/ ... /ttf.files/file.rar
, q: K2 T# f" l) O& q. U' P3 {5 e8 e. M/ N( ]8 c
免费打工仔QQ:1850070
9 b2 ~$ ?0 y8 [. |; k5 C+ v1 _
( h" c% @; P9 M0 uFrom: GameRes
, `2 s4 @2 X0 _, X$ p& u/ Z9 `4 ?. {# e
http://www.gameres.com
6 L* _5 n' n/ d. q$ N
" x) ]% Z' M1 N. W上面图中“免费打工仔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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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