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

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

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

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

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

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

开源的图形渲染引擎OGRE(3) --让OGRE支持中文TTF字体) @" t: b7 ~' z5 J

% w' q7 T  S. m( Q. |2 a" ]9 P0.还是前言
4 v. p9 W2 b" \& l: k! a+ H, ^
- ~* n' R. O5 S8 `- B: I' n        如果你希望能看懂这篇文章,请先确定你已经看到了《让OGRE支持中文》(http://www.gameres.com/Articles/Program/Visual/3D/OgreSupChn.htm),因为本文是在上一篇文章的基础上写的,并且假设文件都已经按照上一篇文章进行了手术。但是如果你只想简单的使用TTF字体,只要下载本文附带的文件,重新编译就可以了。 & n: @1 \0 N! g- U% V4 W  I
/ a6 Z5 N3 S: H* S: u# |
1.检讨 5 m! [- q( H( e! c2 V1 f2 U5 @
& _4 J# h* _) H+ }8 F" T( D
        正如上回说的,我们已经实现了一个位图的字体。但是当冷静下来思考时,就能发现这种方法的诸多缺陷。读入一个2048*2048的位图,等于在显存中保存一个2048*2048的贴图,不说是否所有显卡都支持这么大的贴图,单是每个Font字体类吃显存的胃口,就足以令人心惊肉跳。如果定义足够多的字体类,我想你的游戏的配置要求,在某些方面足以超过《DOOM3》了。
3 x. G& a3 q1 s: u4 {- @
6 N: Y* w8 T- N        而且这并不是唯一的缺陷,文字大小相对于位图大小比例相差太大,导致浮点数的文字位置误差很大,你可以在一个文字旁边看到其他文字的影子。(虽然可以通过增加文字间距来解决。)还有点阵字体本身的缺陷,就是字形单一,不适合放大缩小,一些文字边缘的马赛克,足以熄灭任何玩家的投入感。 & {8 b/ }) ?5 Z$ k  ^# {2 a
' i2 I/ ?% V+ g$ ]! s
        似乎TTF是唯一的解决之道。 & a/ F) t' I0 ?

# K/ y1 H1 u( w( `! k0 i2.基本知识 2 l2 J3 j' C% ~5 y$ O9 K2 i! B/ I

3 Y/ H# E5 o' x/ d% A; w- l(1)TTF字体。
$ t6 B8 u7 m; E. h& {! w' A. T: a* M3 C, ~/ G" Y, B, w7 o1 b" G2 S
        TTF是一种矢量字库。我们经常可以听到矢量这个词,像是FLASH中的矢量图形,在100*100分辨率下制作的flash,就算它放大为全屏,显示出的画面也不会出现马赛克。所谓矢量,其实说白了就是用点和线来描述图形,这样,在图形需要放大的时候,只要把所有这个图形的点和线放大相应的倍数就可以了。而且,在网站上有很多的TTF字库可以下载,或者你可以去买一些专门的字库光盘。然后在你发行你精心制作的游戏时,可以顺便捎上这些后缀为.ttf的文件就行了。包括Quake这样的惊世之作,也都是用的TTF字库。 ! {* F" B: n7 s, P
( t5 j7 t4 f* F( }0 a
(2)FreeType2库 3 w5 I4 L. ^1 g- E! n
8 p- c  p6 `7 n( x9 `- I% ~1 M' n
        在http://www.freetype.org,有一个FreeType的免费库,而且是OpenSource的。它目前有2个版本:1.0和2.0。其区别在于,1.0只能读取TTF格式的,而2.0支持更多的文件格式,在使用它之前请详细阅读所要遵循的Licence,以下是摘自FreeType2.0对字库的支持列表: - U- y. S: [, \. M

& {6 ]0 |2 m9 c$ a* J        TrueType fonts (and collections) / |' x, o, A2 r* W$ r6 d( o9 D
" q% b" f) F; K  W+ f; o7 t3 v! {
        Type 1 fonts
4 q: V$ t  l3 Q( v
8 W7 o, g( O3 X9 t/ K( W        CID-keyed Type 1 fonts
2 c& p; K# A% l( {: H- W% u! @2 }/ p3 C: N9 e$ q4 J* M
        CFF fonts . `/ l" ]8 L" ~4 t0 C
' h* s3 G, E4 `+ `
        OpenType fonts (both TrueType and CFF variants)
6 \: g. y) f$ u: t! T6 t! x$ s/ s2 D' F, C8 U
        SFNT-based bitmap fonts
* f8 k  G) d: m) G. Z3 o- y
& H# ]7 j" _" M6 X/ v; @* ?        X11 PCF fonts
& T3 y$ A( J& n7 L  T! u  U  b2 d- @1 w( M5 q3 `$ c# R0 ^- y+ D" U
        Windows FNT fonts
' h- k8 D0 ]+ e- \" x& }8 z( T* W, d8 f* D+ k$ P
(3)“主体思想”
  @8 U) ^" C. Y+ N. H. n6 v. |4 e! m" _$ ?- y1 H) j7 D( j( e
        请参照炎龙工作室的《游戏中汉字显示的实现与技巧》这篇文章,可惜使用的是Windows API,作者千里马肝,上网上搜一下吧。 & m, z" i* m) d! |* \8 a

! }7 v2 l" E( z6 ~3 R        附带说一句,上面两条都是直接从这文章中剪切下来的,>_<  不要骂我啊,不知道算不算侵权呢。
! M" N7 f. u* z/ N: H; F6 j1 S" a# K, P; {
3.动手术---比你想象的要麻烦
  i& f/ v7 b" F; e( \8 V( _(1)
& N! p! }) K% E$ H, B( B. z: I3 _        首先要告诉字体类,我们下一次渲染需要哪些字。以便字体类可以在需要的时候释放不使用的字体。 7 ^+ J7 h# c: K% O* r4 w

4 J3 Y$ m+ r8 c        在Font类中~
. P: n5 Z+ R8 ]1 S& a6 F7 m/ R' s7 @( t) [- E: Q1 o
        a.增加数据 bool mUsing[OGRE_NUM_GLYPHS]; 用来标记文字是否使用。 ' @% D# \1 M: j) A$ t

0 X+ U# y# i: ]$ `; c- k        b.增加函数 - t3 ]: o$ Q, ~0 K- p  ?" n  |6 f
* F$ c+ U* P& i& f
                inline void setUsing(std::vector<unsigned long>& caption)' `( s4 O: |' a

( E+ o7 F1 W6 ?  P6 S. r                {
$ m# x/ S$ b5 o0 I5 x9 S% D) u0 c5 |( |4 l. h% X3 C& Q" r: J7 W
                        memset(this->mUsing,0,sizeof(this->mUsing));
1 S3 M6 w! G" u' J" i) }  n/ W5 Q7 k8 U/ e( z& T) N. H$ R9 d
                        std::vector<unsigned long>::iterator it;- ?4 o: h1 W" l; L1 }

6 W# D) K! ?0 |$ h+ {; l- s/ v                        for(it=caption.begin();it!=caption.end();++it)6 n; e3 d" g! ]1 C& A# b/ b, l5 o. c

( R, n  P: @6 A9 ]% R                        {
: P! [5 n9 L0 p: E- L9 ^% V; O, C7 y5 k! I  P& v- W
                                if(OGRE_GLYPH_INDEX(*it)<OGRE_NUM_GLYPHS)9 J) l$ J5 d( e+ |5 J, {( B

/ Q' p$ Y* i- L                                this->mUsing[OGRE_GLYPH_INDEX(*it)]=1;//标记文字为使用 0 n! a* Y/ w+ e: w+ Q+ \* B% T

3 H* h8 Y: {' o+ x! x0 v7 n                        }. C8 o- ~. X+ {2 l

5 \( f  m. n8 Y4 j) V                }
4 R: }8 X5 V, c# k8 }/ ]  L9 g0 E& b% L" |+ ~
        并在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。
* q$ h' g/ ~- M9 l(2) ! q) K6 ?4 i' [! r5 E3 K8 R& B; j; j3 i
% [' o% A3 x9 U; @- e; [8 I7 P7 v2 H* U
        然后是修改void Font::createTextureFromFont(void);* P8 Q. q: d6 Q8 r

: I- v- H# {9 R% f1 M) B3 W  J& F        Font类是通过void Font::createTextureFromFont(void)来把通过FreeType2分析好的英文字画在一个2^n*2^n的贴图上,然后再保存英文字的位置。 / `& }. M# d$ W" a
" M; o" Y$ ^2 I# r! F9 q/ M. b
        我们需要修改的是: , f) h& x: O- s  r; v

6 H' @, P& T3 U& ]' I& a        a.从函数中分离并保存画字的FreeType2和辅助变量。我们通过一个类来保存和处理这些变量。
: x' Q. C+ l" G" b2 ~& }! u: c) _6 V- {- G/ @! ^3 w
        class TTFMsg
; }& z  ^0 d* Y
$ V' `1 O& C% F& O7 R! T) d* W/ r, g                {
' A0 y1 M0 U5 b) M$ {$ N1 ?/ N+ ^9 H4 k5 V3 @
                        class Max//类中类,用来保存几个"最大",9 J% p+ i# H( |5 q; V

$ s# F0 w) I$ o# m/ {- ]- N                        {
, W# X. J( B; I! q0 U& P' k, C, ]
                                int nothing;//这个是用来占位的,没意义,反正没他就运行出错,可能和数据对齐有关吧。
4 S2 R# ^, [$ p
6 H' |: s* g) m# o1 f% C! ~                        public:
6 ]8 i! p* g4 Z+ S                                int height;//文字最大高度 : i0 `4 }' s9 d* G
                                int width;//最大宽度 - |7 I5 H' {# p7 f$ N, b
                                int bear;//最大空隙?
; q; P: ~6 ~  V8 x$ t- u$ m                        };7 ^3 A+ ^& d- c+ l5 M+ D$ p  n
                public:
8 t0 {" [. O" U9 R' l                        FT_Library ftLibrary;//FreeType2用
1 }# x- x: M( u$ R                        FT_Face face;//FreeType2接口? 1 j2 q6 p2 B9 d8 [. U
                        uint char_spacer;//文字空隙 9 g  l. ?4 x( R6 n/ G/ G, V
                        SDDataChunk ttfchunk;//数据块,用来保存ttf信息 1 [; z8 n$ Q2 a' ^; P
                        FT_F26Dot6 ftSize;//FreeType2字体大小 6 F6 W* j3 ?: k9 b9 D
                        std::pair<uint,uint> point;//在位图上画字的点 % J5 A' l, I, S- p
                        SDDataChunk imgchunk;//数据块,用来保存位图信息 1 [( [6 \8 U! C
                        bool dirty;//标记,看是否需要更新贴图
( ?0 o; J, u. ]1 m                        Max max;//几个最大 ! Y$ H% y2 D: u( i8 j0 L
  r( c6 b2 I8 G; ~8 r4 a
                        inline bool init(Font*  font) //这个是初始化函数在void Font::createTextureFromFont(void);中调用.
& p' U8 H' i  z; s, u3 \+ W" r2 G6 n/ |6 U& M2 X4 ?
                        {       & }, `4 i8 U( W1 @& G
' C4 g1 C6 k; Y& G( \
                                //以下都是初始化,大部分都是从void Font::createTextureFromFont(void);移植过来的 ; B$ ~# s. w; Y: Z! d

' d* j+ H0 \- a7 S1 A                                dirty=false;
, O9 q) ^2 C# r9 g7 f
% N2 h: ?$ y5 |) r                                if( FT_Init_FreeType( &ftLibrary ) )
( @# X! b4 W$ @0 w+ M3 d5 [6 d+ B
                                  Except( Exception::ERR_INTERNAL_ERROR, "Could not init FreeType library!",. t: k5 I8 E$ h8 i3 N2 R3 e$ L
2 S5 Z, X1 I, k$ U+ t+ Y
                                "Font::Font");
% i5 v* K* l: h) b9 m  g9 f! u% t  e5 N/ ~8 Y& m, `
                + W; K& O* l2 |$ `
- v, s, x- }0 u. x2 r5 w3 f
                                char_spacer= 5;
0 h. E  E; E9 D% [) E7 {% Q7 C
) N  n$ R; A  g  j                                FontManager::getSingleton()._findResourceData(font->mSource,ttfchunk);
, ~/ M# e0 M3 |7 @
, i% o, H( a( A' q: f, O5 ?* p                                if( FT_New_Memory_Face( ftLibrary, ttfchunk.getPtr(), (FT_Long)ttfchunk.getSize() , 0, &face ) )
4 t4 ^& {: T3 F1 u0 F- w0 A% D- f
6 d1 M( W8 s4 i: r& u) ?' O( o( w) y                                         Except( Exception::ERR_INTERNAL_ERROR,
7 z6 K1 O* x8 c2 n
9 n% R" n+ r# C" V1 q                                        "Could not open font face!", "Font::createTextureFromFont" );$ U! d6 C( f2 f- `. P' v

# C- s, w& W* P0 T. ^                                ftSize = (FT_F26Dot6)(font->mTtfSize * (1 << 6));4 t1 e0 e4 A  P) S) B
3 X1 A3 ]: p: m6 I8 t5 @. V
                                if( FT_Set_Char_Size( face, ftSize, 0, font->mTtfResolution, 0 ) ). v1 p, N/ ^# r6 o
8 `" [9 @9 ~" x  `
                                        Except( Exception::ERR_INTERNAL_ERROR,
8 K/ v/ `* a" ?- F! v7 Q+ I0 V; a1 ?0 n+ l% {2 K3 X) y2 e1 W5 ]( }
                                        "Could not set char size!", "Font::createTextureFromFont" );8 d. b8 ]& b3 v3 ^; S  L0 U

, `  I$ N4 T% }  / e* P" R1 `, {& `
- Y* q  ^+ Z0 R) D0 g. S9 E+ l
                                return true;
/ J' g0 P* s* L
7 W( Z* _- v6 Q2 \5 f. X                        }
& y: _) k  \7 V" Q! [' M- h, A9 m7 {! o; k1 [: Q+ \
                        inline bool done()% H2 x: O. Q: l' A) I$ F2 `% |1 ^5 P

: P2 N3 r3 Z7 c                        {. e* |. @' f! I! z

0 A3 m6 Q6 c+ A2 E) l                                //在Font的解构函数中调用的,本来应该调用下面两个函数,但是不知道为什么一调用就出错,不用倒没事。
) m6 b. O! g2 a4 Q! S6 J- {% U  n" D& a4 T9 O8 b
                                //FT_Done_Face(face);$ l0 d/ ]% X6 t; ^& Z

- D0 [: d. ~7 R% f                                //FT_Done_FreeType(ftLibrary);
4 d2 g5 \+ L5 ~5 d2 n9 W
. T* U- q" f8 s; v* @                                return true;
7 |  g/ P5 o& m6 c0 }# V1 Y& A* |! B) a0 m% s: O
                        }
4 U% X4 W5 z& b( a* @. |. k' `( K
; J, b* p' T, X8 c, _" W                        inline bool getRect(Image::Rect & rect)//这个函数以后用的,是用来找到可以画字的贴图的空的位置
+ j* N/ c' |& i* L) W0 V) @; z# w! p- y( ?& a/ p
                        {
& l* \5 A* ^0 Q( u% Z1 C4 j) x' a  s1 Z# [/ T! _/ k. \  \
                                if(511<point.second+max.height+char_spacer)
* u/ t1 g- i$ h0 z& S, W; a, t, E0 D6 ]5 `
                                {
* ?+ ?4 j: Y# i3 z/ x$ j8 E( ]7 w& D7 m1 D2 D! u; D
                                        rect.right=rect.top=rect.left=rect.bottom=-1;8 g" H- }6 U* g2 i
" B$ ~8 t% k& ^' |
                                        return false;
) ]# Y% ~7 T, K, T' Z& Q
. _  T- A  K& X7 R0 }4 v/ v                                }, f7 C* r$ Y- [- g, a4 {, n
* d% M2 r% K+ z* V
                                if(511<point.first+max.width+char_spacer)
! V6 T; b5 k3 Z8 ?3 C- Y. [* u
: A- \3 T9 J: P+ Y; ~                                {
# l! {6 c! p. Y3 n) N5 ^% _1 |: }5 S, F4 x& `) W, n8 v
                                       
; x8 z+ V4 E! J1 N; e# h/ `) r
* h( K# ^, ~& H                                        point.second+=max.width+char_spacer;- F" h+ p; s* {1 b9 c: }! A1 u

: {0 T9 t* y' {9 z3 b, F- D                                        point.first=0;
( z" i: {  Y. d2 ?
( B. R/ M( b& O- t% Q) o/ ?                                        if(511<point.second+max.height+char_spacer), Q: ?. B  S; d+ e; l$ C0 }9 u; ?$ Q
8 f9 j/ K; x! T2 z0 L" |3 \6 o
                                        {8 [  R, M# e6 L& r* |
1 f$ r/ ?1 W0 Q% z) ?  I/ i1 g) H
                                       
4 D1 o8 r. p& v0 _9 L2 c( s  U! i1 z# v* d
                                                rect.right=rect.top=rect.left=rect.bottom=-1;" a9 q. U+ \8 ]4 H
4 N! w/ H% X+ n
                                                return false;
# G2 o4 L4 q  q6 `
9 W- v( Q3 U* _, J2 |- d                                        }9 ~4 Q( G9 v+ j7 b1 R
# l, O" G. v7 p2 T; F
                                }' j" y) _" _3 s3 H- B9 L

' J* o3 o" P- e/ q) b; X                                rect.left=point.first;/ _- Q$ ?. U1 C! ?9 l

# G4 e0 L' R) X* h                                rect.top=point.second;. E) y" A+ ~4 h! V
  Q4 H9 B+ p# V: `
                                rect.bottom=max.height;" P/ g, j5 q7 |+ y' y% S
- G; R' F/ t1 ?& i, s
                                rect.right=max.width;
/ J1 C+ K  d1 Y  h( p7 ^1 q
: J* H( l" T$ g' d                                point.first+=max.width+char_spacer;6 Z' u0 Q& @* a7 [: ~& a& A
7 Y, m/ O/ ~; G# {$ d% A
                                return true;" ~) T6 Y" u% h* Q3 P
, d, m& E4 B7 e. F; K* F9 H& x: x
                        }
/ C4 V, P9 j$ z$ ^- C) O; x7 W2 b) V5 w' I
                };
9 s: h, p5 i9 ?% p7 p3 n& h6 Z" o, k/ I# ^
        上面的类定义在Font类中,在Font中增加 TTFMsg * mTTFMsg 数据,并在构造函数中 mTTFMsg=new TTFMsg;5 p! _. u2 z5 B9 G/ q% M" G

5 E0 h" S/ I& {' ]% g  h        
) J% K% s4 `' K4 \* V
* n7 N# a2 U! J5 k! l- C: X        正是修改void Font::createTextureFromFont(void);函数,主要几点,首先是分离出很多变量和构造到TTFMsg类中了,然后是贴图从2^n*2^n变成固定的512*512,为什么要这个数字呢,因为256太小(废话了)。能保证512*512大小的文本区不会出现不够画字的情况(所有英文+符号+没有重复的汉字),这个安全区域基本上是够用的。(什么,你要画满屏幕的汉字?哪你自己看着改吧。)还有一个重要功能是,要找100个汉字,找出最高和最宽和最大空隙作参考。修改完成这个样子了~
$ a, ]% {; U9 V/ P; [8 g" K% W' v" j
    void Font::createTextureFromFont(void)
* N) v& s( K6 B0 p7 P; s) A7 H; H2 p+ M6 w6 l" W! H3 _9 R
    {
. j1 g+ O% a) g
7 G! R- f+ S# d6 M+ m        mTTFMsg->init(this);//初始化FreeType2
" Z: z4 z7 j! _; U6 i) G2 j2 ^5 a+ `  d6 U8 A
        uint i, l, m, n;
( v+ z1 r& m% N" h
+ Q+ c4 K% X$ Q        int j, k;
* z( e5 E* ~9 H4 ^* t0 v8 d/ x  Z* i9 M2 ]* p3 s
  1 p0 x- R/ Q7 v& F; t' G, u1 c

5 R6 V1 S% _- N) S3 ^( J3 |       $ w: a8 m! ~" b9 f6 E5 P' D
2 N9 P& h' m0 T7 O3 H8 M5 A: z
        FILE *fo_def = stdout;//啥意思?我看不明白
: l4 u; p6 `1 L" A% [9 q
: A% a  i3 t! _7 A: U- N; [7 z  
* a, h( e" {! s, I% E: ~# e* O2 i/ D/ j! g6 I, }1 j
        int max_height = 0, max_width = 0, max_bear = 0;
1 D/ H* e2 t. ^5 ?
/ ?, o2 t  Y0 g/ `$ Q" m) o  
7 q: @4 S# V3 P: W5 c& T" M$ w6 G/ b/ r: y8 l
        uint startGlyph = 33;) s! Q' R% p, n/ X: ?  s

) x: \) ]2 {, |, N+ H0 g, U! N( _$ P        uint endGlyph = 167;% k& G. A, B5 \

) z" q0 t4 z' F% v  }/ b  % l0 s  @  e$ t: c# S- r

4 m, f7 s0 |: P" V; O8 O5 s! V! ?/ R; d- Y        // 找英文的找出最高和最宽和最大空隙 , f) Q' z; d5 Y( [1 l; Y& f

( U' l2 j/ V6 E* W" q7 Z        // Calculate maximum width, height and bearing
; C4 v4 n) {, G0 b  E& A5 L
2 O5 M% ~/ O2 q/ ]0 r        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )# h  x2 c; e9 N8 H9 Q$ A$ z

( g0 ^4 J. P) Q5 G# x1 o5 z6 T        {
- s$ n& G& d/ u  d; t" \4 S2 a# D9 w  c3 n% Q
            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );, _/ @! b. o% e3 G- l) i
% J, C3 y- F: \! M
            //以后的 <<6和>>6都是FreeType2中的数据和我们使用的数据的转换 : Y" H/ l2 \2 v$ p2 C, d+ S
. \3 \$ k( z: z2 }- }! \2 Y
            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )
9 ?1 M  A6 x8 B  E; \8 h! D: r3 c  J* Y# f( b3 F
                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );
% M' y3 l& s6 R: k: V  h
- m" E' [1 x0 A4 E& S7 m$ r            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )0 W( m4 p5 j2 s- A) W3 A" k) g

* P+ S1 C9 a9 @0 x. \                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;
8 j4 Z6 n+ u' H; y  J) K5 \( `  L3 p& P+ s+ q+ Q
  # W3 X4 @: X* ?- w6 L3 E
' ?  W$ ~( W) y
            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)! o6 S2 A' f+ K$ O4 I3 ]" t
7 G! Y+ I8 H& w
                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );% v" L, U+ X. Q* E  Q9 h
* _6 V9 s) [6 k) l2 O, j* T
        }
9 I4 G% M+ T; |0 C- U- D  G1 E) v' ?8 y7 M
  ) w0 b8 g( H" V+ R; C, S
5 |3 n' O4 q- j4 K% ]# i
  9 [) S1 O& \" t3 \* c
! k( o* |0 |9 h
        //下面的for是找100个汉字,找出最高和最宽和最大空隙作参考。姑且认为最的汉字就在这一百个里了。 1 r4 m, L' x& r8 {

: ^2 ^6 \& \% o$ |        for( i = 20643, l = 0, m = 0, n = 0; i < 20743; i++ )
! s3 v& y1 Y, t# M0 w: j& d$ H
" W* T8 k2 O' X- C: ]" g        {
- R) c- f( E/ @9 E5 d
2 {' {" H" x1 v7 D            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );+ l2 C5 T7 N( f9 x+ S: D8 e

9 p% r& H/ A; A4 a+ q  # F' o  }( P. c/ \7 ]* u" R1 S! E
, l5 o- g- ~+ x. ?) u
            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )
4 @$ Q3 a0 M1 _4 E  T, K* {& P; X( b, x. f) K
                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );' B; }9 P' t. s% W9 N& Y# E
7 }$ ~, U3 R: Z3 E* y( H0 p4 P
            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )& E3 i$ }3 F5 z  U

8 _, V) m: C2 P' O# s: j                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;
4 X0 j, A7 B/ |3 V0 q2 |) H* T% r  u6 ?& u1 m5 [+ E- }1 u
  
0 c& d' U+ @$ R( B8 O
7 ?) B; M0 q6 h            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)) `1 X, |) P0 d

* }- H8 v, {: q7 S8 Z                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );  S3 b4 V, A7 d: z

1 j: }1 E+ E- b; z4 q  
6 a# L( V! _2 k8 p8 f+ T1 j( M) T  f! b! O
                        
1 R$ n( d- C& h3 C: Y( D
, ]' y6 X6 z& v" r  D# f            if( (mTTFMsg->face->glyph->advance.x ) + ( mTTFMsg->face->glyph->metrics.horiBearingX ) > mTTFMsg->max.width)" K5 @( g- O7 ~0 ~# s
3 U/ a  Z0 t  p: d
                mTTFMsg->max.width = (mTTFMsg->face->glyph->advance.x  ) + ( mTTFMsg->face->glyph->metrics.horiBearingX );) @) J) F9 |5 F
) W7 L2 U2 R0 V) U5 f
        }0 D# X: |2 P8 S3 _9 L% x8 C& ?# F# ^

) c! w1 n$ D2 o  z! m& q( \# D  / ~$ c+ t+ h( h8 V8 }

4 k1 C$ @; H% _: q2 j, L: R                //下面几行行不需要了 我们要512*512
3 p0 M- j% r( ?/ S. T; x! i1 e+ C$ E' ~# q
                size_t tex_side=512;//就是这个了 512
! V0 h- y% h4 [& Z
* ?& Q* c- g9 t; V$ e0 T2 t        //定义数据宽度 因为是32位的位图 四个char为一个像素,为什么要位这么大呢,难道不能用8位的么,我尝试着改来着,不过改了之后就不透明了。望高手看看能不能改。
- E% L! m0 ?6 `5 p, U
9 A% u% e1 T5 X                size_t data_width = tex_side * 4;
) }2 [- @# B- h3 _6 A( z0 E
4 Z1 i, Y. e7 ~  L/ ?* o* ^  
; M% }$ C3 N1 Q/ z1 Y, j* `6 Q5 r9 g2 J: H% D
                LogManager::getSingleton().logMessage("Font " + mName + "using texture size " +& z* o* @% H5 v* q/ n& f7 \6 n- D

& b7 g, C" X6 V, |                        StringConverter::toString(tex_side) + "x" + StringConverter::toString(tex_side)); " Z1 r. U) u% M: f. x

( J$ H* f2 u& b6 W5 x2 l0 x  
8 X9 M8 L) a) [5 o) J2 M
* ^) G) N  F; C" Y  l. A        uchar* imageData = new uchar[tex_side * tex_side * 4];//设置一个空间用来保存位图   p1 L- a2 r$ O% k. k0 r" l

6 e) F( ?# X. C" C9 l) {                // Reset content/ E, ^0 i2 A( W4 E- S+ T+ @
2 z" [5 W! x1 D: c( v
                memset(imageData, 0, tex_side * tex_side * 4);//清零
/ \. ?- l9 q; c7 f6 r
+ ?; }( t) H' S+ b4 f7 R  ! I( c2 p* X# ~* ^

# K1 T# z/ s" Y- Y& a6 p+ z        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )//遍历每个字, - d* Y' M: w) c% w/ m$ r

; K' ?' c/ }" v9 [7 p/ \        {
6 P8 p9 W5 f. {- N
6 A% D+ P4 N& p8 i                        2 D* }! _' ]' `8 u: {# y

6 E! w4 N; u" a            FT_Error ftResult;
9 N! v1 [1 \' M: J2 Y7 P+ V# S4 ]* @
  
6 D5 p- l6 p$ F: x8 E  l$ @% Y" u- U/ v' Y1 K/ [
            // Load & render glyph
) Q! V: L9 |. d# x( Y# @/ N0 J, L/ v
            ftResult = FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );//读取字体 : p' {4 `  v0 G0 W) x  W
, y% c8 Q) h9 a; T
            if (ftResult)
- e1 I- w& W5 O* z0 L, }$ ~- M6 ]/ H! E  N: @- q1 Q7 p, @
            {: g: ^' E: t2 a) K/ S2 W* v& J
1 f0 K9 j" h2 a/ U
                // problem loading this glyph, continue
6 T  u; Y' o6 c1 R- D4 o6 r( ^  f
8 ]: K4 D! x& m                LogManager::getSingleton().logMessage("Info: cannot load character " +
, Q9 N3 K3 h. D9 v9 m: ]( G# U% V/ q2 n2 ]3 `6 B3 ], ^
                    StringConverter::toString(i) + " in font " + mName);* N+ c" h  q' `4 j5 @6 r! ^1 O6 L

1 i, Y( H# R& ?                continue;//如果错误跳过
. K2 [0 T  s' C+ N: v! d7 A* d/ k: `5 t5 ]3 M& Y! r" Q7 D
            }/ J& q* N4 F) o/ L( z

' D$ D4 u3 k1 `! Y2 H  
! E* v8 G4 i, `" {
% M3 V) T; K" m6 L6 D( o# J7 T                        // 应该是字宽
. r9 h/ O' \& M  z
. V" x1 C; x# T( Z                        FT_Int advance = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
3 p8 D/ i3 K) ?  W* d
$ G% }: N. e) y' B% p5 m! O7 J                        ( ]6 f1 s/ z4 l
+ j5 w! ?: G7 H+ o, w
                        // 得到FreeType2的位图
  d" U6 X+ j' v1 U& T9 b! ^" {" W4 {, U9 e4 Q2 H
            unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;
$ X$ a# L# r# \1 c% a7 o* @
$ l! \: Q+ m0 d/ \- B* _  
( i" K7 [) @0 g7 ^! o" k, ~- r6 j2 V( a% t( {2 t. p, o
            if (!buffer)4 [2 H3 R% U! ^! T
) q( `* n! F: @# s
            {! x. [8 V) |0 U% Z& C" \

) h. f# ^4 [0 a" \+ R8 N6 a. j                // Yuck, FT didn't detect this but generated a null pointer! 7 p, q# j% z# _: P+ K
. Y; A' c6 h$ z. T) K- H+ Z7 S4 N6 D
                LogManager::getSingleton().logMessage("Info: Freetype returned null for character " +
! g, z  r8 A! }8 |7 r
) V3 `8 C: V4 u1 P+ @  d                    StringConverter::toString(i) + " in font " + mName);
& O' X1 K8 ^  M3 {4 V" _
* n# |$ L, @% a3 ]3 r) I                continue;//如果得不到跳过 . p5 `: ?% o/ X! v1 D

1 n/ ]- }& n( k* r- k            }
  S- `; E+ u5 `$ n& f: }5 G, m& ?" p
  & r& O0 O' V& ]5 F: y1 N9 V4 P7 t
; k0 |  F9 o3 r( W3 O  _3 J
                        // 得到y的空隙 (最大空-空-本字空)就是说空出这些字底部就平了
1 t0 G0 b) I3 |0 Q& J. B! o" I1 |* L: n
            int y_bearnig = ( max_bear >> 6 ) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );" c; e: F$ H5 w
; N, g( }2 z4 \5 g3 m
                        & b; N7 p( ?( V+ Y
) [2 O  y  m( w% p& g- y! p  Q
            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )
' P; l: E. @! y. L
* g3 G. V! t/ b" d+ E- D            {
6 k7 R: u5 Z2 x  w# R! x
2 F8 G% P6 P. {& L7 z                                int row = j + m + y_bearnig;//相对行+本字在位图的总行+空隙
* E- \! {) c* m! M
9 J6 a  Y4 Z/ |: ]: U                int col = l;//列 % l0 s0 F6 T. M/ e* V

4 d% r+ e9 C4 ?8 O* z                uchar* pDest = &imageData[(row * data_width) + l * 4];//找起点   # z4 ?' f! D) B8 g! H
8 `0 o" |; |0 ?4 u) P7 e8 y& ?
                for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//画图
% k3 _/ K* g+ F) V4 R: `' v, w% T6 t! z$ U! Q
                {
8 E0 \. D5 C4 d5 C/ z9 s% m/ ^
) m3 z+ c$ Q% t1 S                    if (mAntialiasColour)//看不大懂,难道是灰色字体?
2 }4 \7 X+ f5 ~
. l) E1 u4 P: L$ _  R                    {' q* v/ z2 d" z4 W+ K9 u

8 m2 L7 W) r% o: I' g                        // Use the same greyscale pixel for all components RGBA 7 d9 {6 \. E$ R3 Q
  Z" K% H$ c4 \; A4 @
                        *pDest++= *buffer;% i9 L( x6 _. j" Q

. X) C  f. \9 m% Y" i                            *pDest++= *buffer;
* B  L/ W6 n& C4 B1 ?. S. @% y$ D! \2 [9 Z% O! w2 k# X* o, O9 u
                            *pDest++= *buffer;
( j$ I# Q" t3 `6 F1 a& e5 I3 `7 E* W( }6 s( ?% j: S
                    }
& U0 o/ P, J: ^0 F/ x, u
2 R/ I& |3 l( R3 Z$ ?  K                    else 5 I; r, g/ u  X& C
2 F* J& I* x3 r0 V6 v0 m
                    {, f# \$ a* p, s% S6 w: r' R, A0 q

; N' t/ @# X* h% D( g3 e                        // Clamp colour to full white or off , E3 Q# f/ V" @/ ^8 J) A

' U6 D+ y6 c& K                        if (*buffer > 0)
- r& B& _& M0 ]: V& w) u) X2 u
- F' W4 u5 ?9 B( [  `                        {( h$ @2 g8 N- \: Y' u
* G7 V0 j, O7 j0 {4 u# G8 G; s, Z
                            *pDest++= 0xFF;1 S0 H/ d) G: T

2 s6 m  w( e5 E8 I' v) s' w                            *pDest++= 0xFF;! p0 V$ S3 L; |5 K0 x' d

* x5 c# E& P. L' h' ^                            *pDest++= 0xFF;
: S5 e  }8 x7 M& t: W5 a9 w6 I2 j0 ]4 e
                        }* C; a, c* o# Y. k0 B( ]

- U+ }% e1 A0 S- u7 j5 ?                        else 8 m$ A7 L7 B/ D/ I  l% G

$ @7 I6 F4 A% h1 f                        {$ O5 u  M( \/ |

; v9 M( y! D# W" |* C5 b5 l                            *pDest++= 0;% I; W$ z7 ~1 ]8 [/ r0 @/ y  F) @
. B7 S: n% }0 P& R9 m! A9 @
                            *pDest++= 0;2 i" F7 z1 x& f

& w  T$ W4 T) F                            *pDest++= 0;
! k# H4 m. f3 y0 C: ^# I; e& B; a. E3 R
                        }4 [2 ]: [3 R: K4 s
1 b& R- Z% f9 x) M, W
                    }
: T6 E- X& Y: z( Q
- y& Y" ~; {; ^/ f                    // Always use the greyscale value for alpha - M+ ]$ N  u4 e4 j6 o, l

" b- n4 w4 }; j! A& f/ V                                        + P0 c, I2 `" Q4 P' f6 {8 D2 h$ k
/ [) @# S5 Q! g# g
                    *pDest++= *buffer++;//alpha! 我是一点不了解了为什么是这个?
' B% f( x0 Q5 T1 c
) y4 ^7 e! W/ J* w& f6 u                }
$ P) G/ h/ ]) @. s6 h1 c; n1 ^% e# j3 H' B% C8 V
            }
; }" E& ~" q( ?$ Z+ ^/ i3 e+ l; P
  
( b' {1 Y1 D7 H% y
' j% [4 c. [$ z% ?            this->setGlyphTexCoords( i,
4 G" x: L% t9 S  Q
) d0 c3 Y% [9 V9 y$ n; l                (Real)l / (Real)tex_side,  // u16 U; ]6 Z  P, H
" c' G. o/ N6 z
                (Real)m / (Real)tex_side,  // v1
  c+ j( S( V% F- j) p$ L8 ^! z3 y' }" r6 Q+ z5 S
                (Real)( l + ( mTTFMsg->face->glyph->advance.x >> 6 ) ) / (Real)tex_side, // u23 ~# c$ r& E- L6 \, s
5 h! l8 b$ q7 o1 {* K% l+ A
                (Real)( m + ( max_height >> 6 ) ) / (Real)tex_side // v2
: N! u1 G3 J: G
6 Q8 j0 }+ e7 z, R  E8 D                );//设置坐标
& Q7 [$ j% s5 _2 G5 c8 N  e- X+ Y) @
  
  E4 o2 W7 t* [9 h! g, a, d  y, `( j' Z4 _' l7 C( G3 b. J" X% e/ {
            // Advance a column & z& s% b* l* j5 v& e- r0 B
$ ]- W$ L/ j7 v% f4 q: z
            l += (advance + mTTFMsg->char_spacer);9 V. u1 n) {- ^% N
( F6 q. X9 p7 g3 M1 `$ K
                        //l+= 本字宽+字空
9 k& D( t( q* D
6 {& L; J6 O1 y/ _, {( G' \  
1 j8 {# W) l5 l5 |# L/ q
6 T% d& w8 I% v            // If at end of row 8 \) R* y3 w* s8 P

  r& U" x( t* \% `8 P  n2 e                        //如果到头容不下一个字
3 L& V4 S9 N: [; N* ^( \5 n/ h3 K  M% G4 i2 Q
            if( tex_side - 1 < l + ( advance ) )
9 x" W1 V6 v+ K- j  B+ Y6 N" B
+ r0 X3 w6 [/ Q1 p. P. G4 @- `& w; r3 |            {* f% n, w/ M- Z/ o+ A6 U  m
2 ~( I1 ]! a  g$ a, d, @) d
                m += ( max_height >> 6 ) + mTTFMsg->char_spacer;
7 v2 R% U! e, u% y5 u
6 u7 R6 p' K% z) y6 j4 X  H                l = n = 0;
! p6 ^" x+ U6 X! Q
4 k6 K: J+ o! [' c. y5 K: ~5 i            }
4 v+ S+ m; R2 w1 `$ a; C4 O9 h& `
( ^, x6 U' b, x) H0 q: N, G  R  
* A0 N" |3 e7 {1 w1 g4 i( P; T
% h% |; s/ e7 P  g  H        }8 ~* m; H" \7 e$ ?  f. y' E

* I% ]; i* U7 O% r. C                // 把信息存到我们的mTTFMsg中 >_<
4 I2 n6 M9 w* G: _3 V  q4 V0 {2 f1 c6 n- Q, e/ k
                if(l)
2 b( @, m# F  c5 _3 Y7 w! ?  b" e( z3 s0 U4 k9 O8 h
                        mTTFMsg->point.second = m + ( max_height >> 6 ) + mTTFMsg->char_spacer;
) Q9 L6 Z" p1 |7 N, Z, w& F4 l( {4 ^) J& E
                else
" H; [/ L( i  B5 G) I0 k3 q! P4 h3 X* D- f& r3 A
                        mTTFMsg->point.second = m;
* _! m9 U3 @( O
) h8 ^! {8 {4 B- O$ V* t6 H0 H  
) x+ R/ C: C9 x, T/ z; ~1 {& {  k# D; a. \' [" T
                mTTFMsg->point.first = 0;//另起一行
$ ^+ @3 ]& k$ X4 S1 E
1 n" \- l# z/ I( ?1 w  
* \5 R: s9 a5 b" \0 u: c( H2 n" J  y7 d3 Z& D
                //下面是保存几个最大。
2 E4 i5 b/ D5 K' I& b. X7 U; U
" `3 r  x) Y% _& j                mTTFMsg->max.height = max_height >> 6;
0 b) e* \, H. Z1 m. M7 W* q
3 Q  [: i: K% y+ [% c                mTTFMsg->max.bear=max_bear >> 6;
' M% d# ]' L* P0 M& o! C! R" _3 b
. |! r, \: L0 i                mTTFMsg->max.width=max_width;
0 b1 ^) J! j, Q9 Z- R) E# [* T& J& O% t% ^% [% x  K9 z
  * Q' S+ p+ K6 X" j: Y
" p/ I) W8 M& v5 R' `  t
                mTTFMsg->imgchunk.allocate( tex_side * tex_side * 4,imageData);
4 K' ?2 ^$ Z8 M, m' t9 b9 k+ g( q3 w4 V  S% w: j/ m
               
+ p  }1 \" c+ S& p1 i" r; d, ^" e
7 m$ {- w. M' Z& a+ W9 K3 N1 Q                //不知道为什么要设置img这个中间变量,似乎可以直接从chunk创建贴图
; B9 U: u9 v3 @( ?2 B! O5 r2 D) G! n- \
        //--Image img; / U2 V( c. |+ S6 q% \" O

- h8 O, C  c9 p) l$ ^                //img.loadRawData( imgchunk, tex_side, tex_side, PF_A8R8G8B8 );' A: L* y2 W' ^' h; i# E! J

4 S5 L' }8 l/ P7 ~+ Q  H  + W0 ~( k' T2 A+ `
* P, |2 }4 M5 Q4 |, g) F$ ?
                //贴图名
% N- y; u# @' l' M7 X* O7 l4 C/ Y$ k4 T6 \. G
        String texName = mName + "Texture";9 s& V" \$ C0 z* A4 p7 l* z
$ t; `# a& b* z& S8 ?7 ]
                // Load texture with no mipmaps
; T  W0 v5 O6 U7 c( H: t, d5 r0 }8 }# |1 Z9 M
        // 把从img创建位图改成直接从chunk创建贴图
+ Z5 H( N/ T$ e" ]' R3 r* y6 f- c
                //TextureManager::getSingleton().loadImage( texName , img, TEX_TYPE_2D, 0  );
+ L8 y+ b& t- V+ }2 C
0 d6 q! V, w  H6 e                TextureManager::getSingleton().loadRawData ( texName , mTTFMsg->imgchunk,tex_side, tex_side,PF_A8R8G8B8, TEX_TYPE_2D, 0  );4 n  S9 [3 I$ H3 a

+ x' y$ l8 B- d2 G, Z8 q- L4 a. k        TextureUnitState* t = mpMaterial->getTechnique(0)->getPass(0)->createTextureUnitState( texName );. `: I! E& N  `6 W) Z

5 }7 z) l1 M1 ]' F9 a* W. e                // Allow min/mag filter, but no mip - ~! T6 F+ f$ N! F/ R/ J1 A, ~( H

) Q3 p0 l/ n+ M4 g5 \                t->setTextureFiltering(FO_LINEAR, FO_LINEAR, FO_NONE);8 u  Z; t) d: r1 S( X: @9 p

  f3 k& M  F' a* J' Q" \8 o        // SDDatachunk will delete imageData
- z$ ?! w6 f( R( G/ r4 y% p+ U7 x- j- m  j/ f  \) |% c" a6 Z
        
. s+ U/ X- v  k
( C3 f0 Y, _. Q( y    }
( H9 t2 r: |, A4 l- i7 |' R5 C; k, M/ l; f% x6 f  R
        你应该对照一下以前的函数,改了很多的。
4 C7 V; _- m5 ]& f" ~5 v# j0 m$ ~) G! C
  
" ?: m6 Q9 s3 P
  }1 f. H; w6 V) i  @  F- f$ ]  
& |& ^0 U# \' J  g+ Z3 F4 x2 W% v3 @  t: Y6 ?5 n
(3) 2 Y/ b, v: O) V* l. ?
9 l2 X- B: W# i# N9 w
        然后最重要的是动态的申请和画字。
$ O4 C! K! [; `2 k* ?+ O' j! N1 n  \, ]( v. V* h6 k) h5 O9 K% y
        首先最重要的是我们要一个方法得到汉字的unicode码,我们用到了unicodeMap数组,提供了区位码到unicode码的转换工作,等一下提供这个表给你,好不容易从网上找到的阿,可惜这个表没有中文标点的对应,如果希望支持中文标点,就要努力找到unicode码并加进这个表了。这个表是这样的 char c[3]="邸";unicodeMap[94*(c[0]-0xa0-1)+c[1]-0xa0-1];就得到邸的unicode码,不知道为什么没有5165~5169的unicode码,是轮空么?
9 X* L/ w  r; V+ u& {8 Z4 M1 }  {8 F! h: ]8 R, c! h! i
        4 ?$ T( u& Y5 O8 F
6 ]* z( q; X/ V$ v3 T
        申请渲染(字) # d( W% t) x1 }. i* H2 d5 F
2 P; Q0 D2 L- s
        {: r, H% J; Q3 }# x! i  `( _
3 x! m9 _' X) w" i3 J
                if(有这个字). N8 U6 s, O5 |- c
" `& B) e% S  |4 N' j
                        返回位置
" \% D# a' p. C/ ~3 }' b2 g2 H  h+ _6 Q8 Q$ h. f& h
                else
  f1 x1 \( [. g, L3 p& [& i, I" {% v- Q% b4 G  x5 n9 e
                {
7 H! o* X2 x% J+ y* h% U
2 O% p) G% |6 i) J1 }, C. l- i1 F                        if(有空间)
* D7 v2 c6 e, ^! n7 X  ]
; A* ^8 n% G, ~/ g. R% A& {                                画字 ' j. T4 F, Y) }( J
0 A1 I& y1 Q# L. Z! W5 |
                        else
' ^  j2 L$ H! p" q0 X5 o+ n
4 `; A" f2 X8 l; g) ?" n0 ?                            找不用的字//找不到就出错,没地方画了
2 f6 @; F  w  P  l& t& r) B( l2 j
8 V: {0 B7 |# A" a% ?                                删除 在这个位置上画字 8 Z) D' W. D3 ~! D! ~9 U, [& y

+ m6 m5 b! a' l# v) I% ^                返回位置 4 B% B/ l# N. P, Q. V& @& ?

9 f2 v. n+ c+ W& {! z                }3 c  k; a* l6 C) V7 P- [) G

" Q4 h! L1 ^% ]; p8 H* D        }6 U+ [8 [0 y$ ]2 \
: L. }+ @+ m- i$ n7 v
        上面很直观把,大体就这个意思了,申请渲染的函数是inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )  const。去掉const改一改。得到
; R, g/ D4 Q7 j% S' X) f1 V1 o- x: E2 ~
$ M; s) ]; L) A/ h        a.申请渲染 + y4 D% ^( W  W& \& ?
& w9 z% r* C( b
        inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )         
$ E. e) Z% `" }4 g' R7 k+ \: }) B' h+ m& X. y7 o) M( l1 F
        {8 H# \. y; l4 l7 p( s+ \( I( Q+ A
/ C2 I' S7 ]1 i* t7 x" z1 b
                unsigned long idx = OGRE_GLYPH_INDEX(id);' F. u& b. |, R& A7 I# {

1 e( a: r9 L8 T, m6 k7 y& S                if(this->mType==FT_TRUETYPE)//ttf?9 H! W- S0 i# v) L$ N8 z/ \9 P) M

1 |- n7 D% k3 i3 F/ u                if(id>=161&&idx<OGRE_NUM_GLYPHS)//汉字?
8 V; W0 k# |( @% F: A6 y, A+ h1 I4 _
                        if(!mTexCoords_v2[ idx ])//没有?
/ t' F# h7 F$ k/ w
- B5 I& q. i2 R) X/ ?& `                                setChar(id);//画字去
3 b4 L+ z8 h! q! p  J7 l2 S0 U( f4 @0 j/ A& M( M+ ~0 x' I+ N
            
4 O# |2 Z1 X3 L$ I/ f' R
3 J7 q' h4 V2 e            u1 = mTexCoords_u1[ idx ];+ M0 D% o1 G2 C+ ?
* V8 c+ u  l' w$ ?
            v1 = mTexCoords_v1[ idx ];* k  m2 W: D  y. D+ N! e

4 i7 T/ }2 E. L. }0 m            u2 = mTexCoords_u2[ idx ];
% ^1 s: Q' T0 r3 D0 Y& ~) h* C3 ]2 D+ Z4 r8 L8 J5 R  [) p% O& u) O
            v2 = mTexCoords_v2[ idx ];. f4 `- e8 ]$ L% s- b) Z
* z$ A' X' P6 w3 V7 b5 b; q
        }
9 l. |* R5 w& o( U# O4 U0 G0 B+ X2 u) J& t: V' J/ Z7 Y
        b.画字等
* ~1 X) `5 C- A' L3 R5 z
- l+ M) |4 |5 P1 }. e+ k        bool Font::setChar(unsigned long dwChar)
- B* T6 }. |1 t- G* p/ y
* R& ^' X& V- G6 ~        {8 L8 E2 w3 G7 L  g/ T$ t
& z: \. y# T8 H2 H
                int j,k;
4 b6 f6 l( H6 d3 c5 j3 x
6 v( t& R, O: N) L  e                uchar* pDest;//操作数据的指针 ) X. y6 b3 y: s) |, G' Q( v( x

' s( o9 n1 H: \' k, b# f                mProportion=0.8;//不知为什么,总觉得中文都太扁平了,所以设置这个参数,在《让OGRE支持中文》中创造的参数 6 V" t* m* U$ O5 j8 Y2 W2 l1 q
3 x0 j# B( e. |  S
                Image::Rect  rect;//画字的位置 ( n0 X; l* f: G

6 _. O! ?" _+ M: ]! |" [8 f                if(!mTTFMsg->getRect(rect)/*回头看看这个函数吧*/)//如果得不到空位置 , z6 e8 w5 g) P8 K3 I8 n0 ^

* w1 P- }  X- l( v1 ~                {
, [+ C9 X' C# Y6 P* O9 D. O
# T8 U  G% ~+ T; }. t* ^+ O7 v8 W# |                        for(int i=161;i<OGRE_NUM_GLYPHS;++i)//寻找不用的字 & V. P8 K  y) c* ?/ Z& e2 }% K

$ v0 Z- F0 g% j                        {, W- L' E* M1 C0 n' j6 E/ Y7 _
. {+ ?' [  q7 y" b/ @
                                if(!mUsing&&mTexCoords_v2)1 w* V: h& A* ?6 }3 a% [/ z
  ?4 o. c! _7 C% p0 g; s# S
                                {
( c* W  k" t* E+ X6 q+ ~; |3 C: k7 k& V
                                        // 得到坐标
* v7 u& y  y7 }8 r1 V+ }  c4 _5 I& u9 ?* `
                                        rect.left=mTexCoords_u1*512;. W! q# _' }' Z+ e! d
& H: {3 b9 W5 A( U
                                        rect.top=mTexCoords_v1*512;
( e$ B# Z3 S  Z; X
' n4 b8 ~3 k+ T$ G                                        rect.bottom=mTTFMsg->max.height;
/ N; @* w, j7 Q$ X- ^8 a  v. m! V: N/ r0 U6 z  `% M
                                        rect.right=mTTFMsg->max.width;
# h8 X- l/ t+ G' w% {
8 P2 B: m# U# c9 R9 D  : g# E' u! k9 X3 F; D  r4 z

, U/ P, j4 n8 `& N                                       
2 O! @8 }" ^# c* B' C, W" G( w( f; B; k3 l/ X4 J/ x
                                       
0 ?: f3 w( e& W6 C& k" m/ y: g+ s8 E; S% I! Y
                                
' r' K5 q; t' u( N0 X8 k# w9 r; a7 [4 @
                                        //擦除(这段代码没有试验过,等做完输入的类在检查吧) & W. o' j" Q- C9 p( ?' ~% u& G) Q

& B2 ^1 k. P) N, i8 r& @                                        for( j = 0; j < mTTFMsg->max.height; j++ ): B3 @6 s( F% F  e

# N( I$ O; g$ g: U: T+ U1 a                                        {
# x% n; k1 x! _/ w/ h9 r- D+ `+ ~& W. W* W+ n
                                                pDest=mTTFMsg->imgchunk.getPtr();
- F& a, l- ~# U" S/ c  p- M& Y. i7 z2 s* V  Y6 K; ]
                                                pDest+=((j + rect.top)* (512*4)) + rect.left * 4;9 t& i+ |% h" g/ H! }

/ f& i0 }9 N9 t! X! l( w                                                memset(pDest,0,mTTFMsg->max.width*4);
' |( E6 N; E4 x( i7 z" ~# R2 M2 q8 v7 h6 s
                                        }' M' y) p3 B. \9 _

! x4 V8 g3 J) V$ C8 Z2 u                                        mTexCoords_u1=mTexCoords_v1=mTexCoords_u2=mTexCoords_v2=0;
/ X( C* a/ @- i2 E1 [8 s9 K0 c' J0 _! }6 o3 y$ x" p! m0 s* X
  ) k5 s/ [2 C# G2 L0 Y% y
) x7 ]" ?2 Q  ?: @3 f/ `
                                        break;
. I- T8 b4 w: E# p
/ W% V; m' c! A7 M, ?1 ~( N                                }
7 b4 H8 K9 i; R/ O, N
/ J8 r* R1 {8 H. N                        }
+ \# O& g0 J2 v4 x3 e# L& V& d
( f  K  g  s6 q1 U+ l# B                        
3 A- Z1 F. N! w$ X- }# ^2 Y2 a
; a# Q; d  x' b, Z+ ~7 y& z                        if(rect.top==-1)//啊啊啊啊啊啊啊啊啊,贴图竟然都用完了,没办法了,出错了
+ N% w3 {* M! j# P, ?* V6 R# a5 W" ~6 m1 A* f9 V, G
                        {' d0 Z- b( }7 i5 b' Q# }' B# _+ Q
, O, ^+ j9 i3 a# A; {
                                LogManager::getSingleton().logMessage("你太贪婪了,用的汉字太多了,这是对你的惩罚."); , k% l+ d1 \8 R# A2 {5 }+ R

" q: h, C) v( T# p8 R* v4 O+ W% o5 S                                return false;
8 n1 F! ?- E7 ~, w+ C; }' B- w! h5 Q5 |( }+ a& h
                        }
$ \8 X1 E4 L, O4 i0 L( L/ Q# l9 j2 G7 D# j! t, a( N) E3 V
        4 ]' W7 L; U! Z
  w% g' x7 u7 v# g7 o
                }
. d" u, I' X+ A  }2 |* \: Z: G
( d& i3 o, K% m$ D! D8 ?                        
7 l% v. s* p/ Y
& y# x4 _" ~8 q               
0 f: r! |. U4 a# S
7 _5 N% d, n7 N* r) \& a; o8 m                  //以下画字的都是招葫芦画瓢的, + v& h5 }/ h3 f) b, k

% _  l6 v, s4 j. X                  FILE *fo_def = stdout;
" S/ F+ `# J! h1 ^
+ t. W* C2 x# e! N1 o2 W                 FT_Error ftResult;
) a2 p& {5 V& y- ?9 J
' d/ D1 z+ c4 Z" j; P  0 X8 p7 r5 X, O1 i; k0 J$ h, m

  M- [4 H7 z7 Y            // Load & render glyph
+ B; ?4 J' F* S3 L# `3 a9 @1 p/ l) h9 r9 }& B
                  
+ ]9 U4 @! e/ y9 n! F* k# a
7 m' {0 s8 i' L            ftResult = FT_Load_Char( mTTFMsg->face, unicodeMap[dwChar-161], FT_LOAD_RENDER );//读取字体 0 J9 K7 c4 g( k8 N. F2 U
( h; C5 q; O" h3 {
            if (ftResult)
7 a6 y# v. N0 O8 t* [+ @
4 c) ]* \0 b$ s& ?& f; z, L            {% b# f, Q, {3 E- ^8 y( W) A8 j

: ~9 |* a8 x) ~7 x, p                // problem loading this glyph, continue $ ~5 Y; T! W/ o
! n8 h2 O) _6 Y5 P6 z
                LogManager::getSingleton().logMessage("Info: cannot load character " +
4 v& ~& t, I: t
6 o0 W  Q4 x8 r# R: }9 `4 |  |4 G                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);
$ P  o0 x& _. g' F. B/ p, I& u9 K3 C7 h3 M8 i, u& W4 X3 X
                return false;//如果错误跳过
* R& }+ B3 a- U0 }2 }3 i' V. w; V
3 u0 M- a5 w3 X- q' K            }
- T# A% r% K, V3 F( a
0 D; M/ J: `$ E0 E  2 o7 @/ U- q8 t0 e* q
( o; J$ Q$ K! a9 @2 I- I1 m. Q5 D
          unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;
/ h  i" Q, \9 ~& B4 n. m4 M$ N& a8 Z5 `2 I) X- m% U. `
                  // 位图指针 . w; W) g6 o3 k# S" B

8 o" L% u) c6 t$ U            if (!buffer)
+ \* u  @$ p# N* Y, i. s* v: `2 E% l0 e2 R
            {
# H; J7 W4 p5 ]* U5 O+ z
$ R% ]& y# G2 K$ c1 ?                // Yuck, FT didn't detect this but generated a null pointer!
: {+ B4 v3 i% E: ]( s
+ S& K4 x. B8 O0 X9 X' s$ R1 d                LogManager::getSingleton().logMessage("Info: 1111Freetype returned null for character " +
  U/ m- i/ D. Q9 L* t0 R# n! A
                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);
1 v' X: D7 N) h* p- q  e! k3 X  y9 K' ~1 U0 C' L
                return false;//如果得不到跳过
2 ^- M! C- }  q8 I9 S# v2 N  x: [  @4 f$ d
            }! `- v8 S, i; b

3 R. A$ P- p! J; H1 n! t8 L  5 c5 t! l, S' z

" ~% b5 e% G- j9 m, V                         int y_bearnig = ( mTTFMsg->max.bear) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );
: D- A4 d3 W+ h$ |
9 ?3 z* ?6 e% B: H7 ?  f      
5 I' P' A7 ~( T2 c6 D- f5 [
2 k0 L7 O1 S( J4 ~0 R6 d                        
1 Q% e1 K0 f& `% J' Z- m, e, n. g. u3 v8 P3 ]
            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )/ O! I& d/ I9 |8 ^/ ?

; ?1 `: c1 F9 _            {* K3 u9 b& c0 \/ C7 b* t
" _& F& \$ Q: |( O
                int row = j + rect.top+y_bearnig;
" n* p; V( O4 p( W1 P9 d+ O
( G8 ~2 q' `6 W. {0 y7 C                int col = rect.left;//列
; ^  n  n. \9 |! P& a9 {* m4 x$ y& g/ V% s, |! I/ N5 b6 L
                                pDest=mTTFMsg->imgchunk.getPtr();
1 h! E1 y# T! O- w7 Y9 Z: `6 s
, N% r2 @. L4 e/ L( a  n  ) B7 ]( C4 a/ i7 V: I$ ]
4 [; P3 h5 G% [( r) j
                        " O$ o3 V# F* T& u$ D% C/ s5 \: \
7 U4 _7 n7 {( x
                                pDest+=(row * (512*4)) + col * 4;
7 A  J9 F( y' K& O  h
2 H. E1 u+ o2 ^0 e( o5 r               for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//每行的点 $ ~. P" I' @1 f, p5 X$ g# p

) j4 F2 v" T! d                {
" n6 F. l, L2 P3 H( U( ]- C/ h; X0 A3 [4 z; u4 K5 K
                    if (mAntialiasColour)* i" u- {0 h* Z3 g
* _" _6 s" t. `% ^0 v, Y1 p3 ?" K
                    {
) v( b! o  V/ d
0 \0 ]% Y& {$ b+ \; F                        // Use the same greyscale pixel for all components RGBA 6 d, s/ R# z* ?% u# x" P$ ]
8 o9 E& A7 t" d" {- L
                                                        *pDest++= *buffer;
) y9 U$ _4 L! B9 `2 P3 v( q0 T. l& w. |2 r9 e
                            *pDest++= *buffer;
8 d3 d6 U0 g; ^* K' u) D* K$ G- [6 |. X& `  ~- L2 M2 L6 K( |8 j
                            *pDest++= *buffer;
1 z) M" \, V4 ~1 s. H5 c8 v( G* {5 S2 p! K. I" x, \
                    }
" j* e1 ^  Q8 E
. H) @7 d: p+ ]8 B7 y( ]                    else # e# j3 F: n4 ]+ X: R/ ^  E

' f& r! E( e6 f' g8 k' I9 i1 s                    {
# F2 m1 t+ h( F# X" j8 v/ G2 M
6 a3 F, y' T' c  j( g2 u                        // Clamp colour to full white or off
. U, H( |0 ]3 U0 R$ k! l" ~+ B8 }: Y: P5 m: A2 P
                        if (*buffer > 0)" [4 u3 Q% O9 c# I+ B/ k5 {/ n
) B$ q. S' \( H
                        {5 Z& R0 s5 S1 J3 Y2 T

* s1 K1 l8 F$ \' H8 s+ v                            *pDest++= 0xFF;: q; W# J1 i5 V1 ?4 L$ k  i" V2 l

  p$ ]" [2 j: Z# ?6 Y+ Q                            *pDest++= 0xFF;3 I% I  k/ q% [  U) q/ r$ c6 x
. E( S0 X. s5 h- |3 y
                            *pDest++= 0xFF;2 `, Z3 e3 J; B" Z  `
) u) I/ @' c1 {9 ^' \) T( S- ?# t
                        }, D% u" I5 i9 x' Z" Q

! n" g4 E8 I0 j' C                        else ; \4 V, M" _4 W! {/ n: d3 b
) J- P9 [) R. r7 m
                        {
2 {8 e5 u+ k% J" i0 A& L! D. V+ D7 _# `6 n  m
                            *pDest++= 0;
+ S3 N& g  p. j( L! C. i! \) a7 \8 d! _) f. W% R' ]
                            *pDest++= 0;
% q- o5 r* g3 s4 i' W2 H2 g7 h/ `# p' r, e; k3 A. b. P
                            *pDest++= 0;( y; ?! j. L& _1 p" {' \

. \+ P  T) C4 h$ ^                        }" G2 M9 t3 @1 P& H2 m
- b& d$ u8 s, e* E2 y/ F
                    }
& l/ M4 x  G$ y9 f! U( p% ]
+ R2 P  d/ n# T0 C- k1 W                    // Always use the greyscale value for alpha
: @  _8 y6 j7 ~9 v8 n! R, h, Q
3 u% z& r# C. X! B8 s9 P7 R                                       
/ H! z" \# W) C- y
% \# w( ?, e6 O" E/ I6 ~                                //      LogManager::getSingleton().logMessage(StringConverter::toString(*buffer)+"is cool");. o% D8 e1 V. t/ X
- h  j) B" d0 B/ e" p! K: ^6 z
                    *pDest++= *buffer++;" [. z; B  s" j! z) _& M; g% c

; z5 F) P  T: f% ]$ j$ j9 U3 a& p                }
8 J* Q# q: X' e& u0 j+ `
6 @- {: J  W$ R2 ]+ j" l                                + U6 z( s% l  G

2 J1 o) \. l" q' l% P! F                        }8 |* y+ Z# p3 {8 q& Z" L/ ]
3 r3 I0 G2 H. W/ t8 ~/ ?# Z+ n0 [
                        // 设置位置 0 e. I, G/ U4 w4 P1 j% x7 K# V
8 m# B+ e0 ]8 L8 {
                        this->setGlyphTexCoords( dwChar,
+ m+ W, \0 i* F; z8 d& l
& w. p0 O- k, F& ]" x/ a                                 (Real)rect.left / 512.0f,  // u1
4 L$ Y0 j6 f, z5 K* ?% T
' a. h. B$ x) B                                (Real)rect.top / 512.0f,  // v1
/ R6 H' H9 R; `% v- Z+ G
" {9 F: [+ b- n6 \3 Z4 F0 ]' j  y                                (Real)( rect.left + (mTTFMsg->face->glyph->advance.x >> 6) ) / 512.0f, // u2
9 t; c3 U4 p  n) {1 ]+ i' B& v9 j: Z7 l+ c
                                (Real)( rect.top + rect.bottom ) / 512.0f // v2
" o7 t$ H- t7 c5 R
: H* |$ ^9 s9 p8 d- ^. ]% ~                                        );
) M4 w9 R9 C# M, M7 H# }/ [% n* k0 `) w5 U' y  u7 U. N; Z* U
                mTTFMsg->dirty=true;//贴图需要更新   B, G. G, ]% G; {! w
; \! b" k' ]5 q# ?$ K* @7 |
                return true;1 F/ E+ b. n  {8 j* o6 t. h
' q# C; m1 c4 |. p& X7 m
        }
& b0 w. D  K0 A, M1 T
) G( _# ~# X: _5 i  * ~: N- ], }8 ~1 |: O. v. f8 h7 `. T
/ X8 W& M% p  C4 p4 y
(4) 1 X! v% Y6 A- @( w1 X& l6 F
! m" r8 {2 ~$ Z7 j
        松口气吧,繁重的工作都做完了,就是更新贴图了。
4 {* D1 I* I2 U& ~
8 |' [& r- H: v; C0 Z        Font类中~
# m# s5 T. c* k) p/ u, C  l5 a- H$ W. N1 b3 f, A
        inline void write()
% }8 W" e8 j0 K6 ^. X
4 {% O! W% ~: i                {' I6 Y2 Q/ C3 A, o1 z/ N

4 T, j! _' P  Q8 P) L% u3 \                        if(mTTFMsg->dirty)
6 f" x! e: K9 H; _& M' J8 F7 F# k/ x, k% n) D
                        {      
. V: o) X+ |" R1 L8 P
+ T. D: |( v8 n, o; y; S                                // 重新载入贴图,顺便说一句,类似功能的函数还有
. n( K9 F, t( n) x. m. m/ v0 B7 E0 K3 Z2 k7 R8 @2 v2 w
                                //virtual void  blitToTexture (const Image &src, unsigned uStartX, unsigned uStartY)=0 , r. Y: v: d' m1 I; M3 Y: B

& O( Q& Y- J3 C+ ^  T3 `                                //和virtual void  blitImage (const Image &src, const Image::Rect imgRect, const Image::Rect texRect)' f+ \. x7 N- p7 M
/ E+ p" v4 y/ x! t5 [& M$ R
                                //不过blitToTexture()在ogre-win32-v0-14-0之前没有实现,没有尝试使用。 blitImage()就算到现在也没有实现。
1 {/ |) O7 U) q2 ?9 u' Q" Z' I; V; r4 P+ }
  
  g/ F# o* m7 {" l# C& g' r+ d8 U1 E. p+ f# {
                                TextureManager::getSingleton().unload ( mName + "Texture");
- a/ r1 L* R: B( n1 B) p- U: ^
4 Y+ D" a5 Q% c$ m2 a7 @! s                                TextureManager::getSingleton().loadRawData ( mName + "Texture" , mTTFMsg->imgchunk,512, 512,PF_A8R8G8B8, TEX_TYPE_2D, 0  );
% d1 d$ u: ?: p6 V* \
4 Z- F) H% J2 k/ ^$ q3 A$ s" U; c                                mTTFMsg->dirty=false;/ Y" L* s  U, i+ R
% [( J7 ~7 _' m) n
                        }
9 U' r! S+ w) j' A' z& c% A4 Q. O& r! v7 J( ?4 b9 o3 i
                }
0 Z7 d  j8 [% J) j( c6 I
6 k$ `6 i4 M3 q1 p0 P- ~+ L& a  
. r' x! V7 k% b. x/ d- K" F
' l( G' S" @% F$ o, z8 _         在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。
4 X2 J5 c1 o. L0 U+ A# J8 x. E% X
  , P+ w/ ^3 `$ L* [' o* M% x
- H* c! y8 w, m8 P" K, i, h
  2 G0 }; K9 S7 e" J0 `/ H
0 e- a" N* g  ^# _& U
4.结果。
/ \4 D  T, `) C! |. E8 A& @+ D# s% o
        好长阿,写了好长。虽然多是代码,但写注释也很累啊。重温了这些天的工作结果。就像上一篇一样“在OpenGL和DX9.0中成功的支持了中文,但是DX7.0中竟然出现了运行错误,具体问题还不清楚,还望各位高手指教。”。不过本来OGRE就不怎么支持DX7的,不管了吧。OpenGL中渲染的比DX9.0清晰,是我的显卡的原因么?以上的winXp+vs2003.net+艾尔沙980se通过~。。 2 b# a9 o* G' m/ x* I! c# S

: }% a" A# N% S/ K+ Z# l1 _% p$ E        顺便说两句,上次发表了拙作,没想到好多朋友和高人们找到了我。甚至联系到了一个南方的公司,说要做一个引擎支持中文的方面。但是卖完400多的火车票之后竟然因为住房问题作废了,5555,退票少了80元啊。还是自己差阿,如果再多学点可能就能要我了把~。努力吧,争取写《让OGRE支持中文》三部曲。 * r8 R; T; E2 F# i5 q. Z/ x& Y
* K0 H% h/ R; S- N7 _# b
        下一篇应该是《可以输入中文了》。 ' {1 E9 s. T% m. A; P
$ T3 ?- o7 r, f1 I7 Z- D0 ^
        也可能写不出来的~~~~~~~~~~~~~~~~~~~~   
: ^# b' ?! B$ x* i
$ R; ]# _0 n8 m" B; ^2 h* {2 ^; b    相关文件 7 A4 e! e" e8 ]" ]7 V9 V

& X4 D  q+ T6 G$ P8 l/ \    chinese.fontdef//字体信息文件 放在资源文件加中 " f. Z7 y6 V  C0 x# i* ^, c

1 }- x3 P! F$ t0 X/ W    font.png//字体图片 放在资源文件加中   f' q& h: x/ E$ p9 n$ `

, a8 N) i8 G+ Y! m3 u2 u/ m  + T1 z$ f; |9 z- c4 [2 d

, M8 z0 a4 T. ]1 f* U+ _/ \5 i# \    OgreFont.cpp( I" v5 N( G* Z3 I

: O  }  Y/ R) r1 |# m# I" ^/ t    OgreFont.h
5 x5 v2 j# z3 @' L
" o7 W# l0 T: B# ]4 t    OgreFontManager.cpp. ~/ w& Q% ^$ G

$ N1 E4 c7 w+ I+ a. D    OgreTextAreaGuiElement.cpp
8 h. m7 q4 j# g- ?9 U  m8 C: P" y8 o
    //上面文件覆盖同名文件 就可以 先备份 " D; O/ g, X2 e' |  g. u- J

- w0 C4 T( [5 F0 J   
+ b+ i; k( z; V+ n2 B$ f
8 P( @6 V; w. Z3 z. H1 G% y% Z   solo5.ttf//这个是一个中文ttf 我直接替换了原来的ttf
) Y- |& v3 |/ _2 s( @: ]0 O0 s3 x4 @; W' E2 _. J7 o
   unicodemap.h//这个重要,是换算unicode码的数组(文中提到)
4 n2 E" u/ o7 @  T, \. {; C. T' J1 g: K# `# _3 B" j5 D
  $ H# g0 X  Y6 F* v
+ A" ?) Z% t8 Q' a9 h
这个是在ogre-win32-v0-14-0基础上改的(上次是ogre-win32-v0-13-1),
2 ^% I3 U7 ?) ]( N  \6 M* U. G6 z" N7 O; L3 r$ a) i
请到http://sourceforge.net/projects/ogre/下载 / e% `) i$ G; O% n9 Q
1 i+ e$ A% k! _) M
配套档案下载:http://www.gameres.com/Articles/ ... /ttf.files/file.rar
% y4 R( _7 ^0 ^& B2 A5 ?' K; e8 k; N/ V4 }' l4 T) `3 M  b
免费打工仔QQ:1850070
  x! Z) C) p$ g8 x( w1 |" L
* z9 p- V  K  n0 UFrom: GameRes
4 h2 j. D. Y0 [% w, m5 l) X: V: N8 X
8 e0 A; N8 o6 S3 Zhttp://www.gameres.com
1 b  U, u/ g# C- x) D3 ~
$ F; \3 O6 a2 z" k0 q3 U上面图中“免费打工仔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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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