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

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

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

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

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

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

开源的图形渲染引擎OGRE(3) --让OGRE支持中文TTF字体: }: ^. _# `4 B; Y* X$ H

3 e, U2 b9 L1 @+ H# D0.还是前言 9 k+ g7 R. ^5 F! k

; s/ l/ S7 O! P        如果你希望能看懂这篇文章,请先确定你已经看到了《让OGRE支持中文》(http://www.gameres.com/Articles/Program/Visual/3D/OgreSupChn.htm),因为本文是在上一篇文章的基础上写的,并且假设文件都已经按照上一篇文章进行了手术。但是如果你只想简单的使用TTF字体,只要下载本文附带的文件,重新编译就可以了。
# L9 c6 a# ], s# t: L/ ]6 N
- j; E! V6 a: C) s0 U1.检讨
/ u6 j  V# t" T) Z) L# M+ E/ R7 J  Q/ N
        正如上回说的,我们已经实现了一个位图的字体。但是当冷静下来思考时,就能发现这种方法的诸多缺陷。读入一个2048*2048的位图,等于在显存中保存一个2048*2048的贴图,不说是否所有显卡都支持这么大的贴图,单是每个Font字体类吃显存的胃口,就足以令人心惊肉跳。如果定义足够多的字体类,我想你的游戏的配置要求,在某些方面足以超过《DOOM3》了。
5 z  J, K* V4 E1 _# H( p7 o- ^' M  f; m7 `' t: w* V
        而且这并不是唯一的缺陷,文字大小相对于位图大小比例相差太大,导致浮点数的文字位置误差很大,你可以在一个文字旁边看到其他文字的影子。(虽然可以通过增加文字间距来解决。)还有点阵字体本身的缺陷,就是字形单一,不适合放大缩小,一些文字边缘的马赛克,足以熄灭任何玩家的投入感。 . |8 w. U* T9 e( J* t0 I

" e2 s5 M9 j5 u4 m- Y" k        似乎TTF是唯一的解决之道。 + R3 h1 o$ \# _% |) U2 _
" n! J9 X- v" F
2.基本知识
9 l9 p/ e9 _% K
( G& s, f8 F: l) Y(1)TTF字体。 8 c9 J' l; ^. X# |/ _, N5 h3 z$ m
6 O9 R) T& k* @- u
        TTF是一种矢量字库。我们经常可以听到矢量这个词,像是FLASH中的矢量图形,在100*100分辨率下制作的flash,就算它放大为全屏,显示出的画面也不会出现马赛克。所谓矢量,其实说白了就是用点和线来描述图形,这样,在图形需要放大的时候,只要把所有这个图形的点和线放大相应的倍数就可以了。而且,在网站上有很多的TTF字库可以下载,或者你可以去买一些专门的字库光盘。然后在你发行你精心制作的游戏时,可以顺便捎上这些后缀为.ttf的文件就行了。包括Quake这样的惊世之作,也都是用的TTF字库。 ! h, b5 T4 [3 y8 k- }$ |

# y4 ?6 p7 a; _; I4 C$ y. ~2 o(2)FreeType2库 4 y5 ~# B' A9 H1 J$ z

/ E, r8 n) A6 c- g4 [& C7 I2 Q4 a, U        在http://www.freetype.org,有一个FreeType的免费库,而且是OpenSource的。它目前有2个版本:1.0和2.0。其区别在于,1.0只能读取TTF格式的,而2.0支持更多的文件格式,在使用它之前请详细阅读所要遵循的Licence,以下是摘自FreeType2.0对字库的支持列表:
- I- Q: @- j0 |
# N, _) R7 X1 ^0 T' ?. A        TrueType fonts (and collections)
2 ?/ R5 K: B/ I+ _' g
+ b. y3 r1 Z4 q- u        Type 1 fonts ! S5 b/ a4 x" G: K1 |

$ d/ A/ d% x: h        CID-keyed Type 1 fonts
% J- U2 M# i# {- o
6 `" E* C7 t/ {5 \* s2 ~6 g        CFF fonts
8 Y: ~/ f; Y9 _! `7 B( ^0 f0 R% F8 v# W& F% z% R
        OpenType fonts (both TrueType and CFF variants)
: |3 i5 p( Y9 |4 T0 F
/ h5 l5 t! Y$ u; u+ n' y        SFNT-based bitmap fonts & H! L) r/ i& R: v

( G. P5 r: G& o& j7 c: d! ?        X11 PCF fonts / r3 o* @/ O- V3 P9 V: W+ N

; @; l8 l  e3 @; [- I0 s# g( ~& y        Windows FNT fonts 3 w: M! i! K) e/ v

5 I5 ^7 X0 k* U* b3 x9 s( g; w& n, |* w(3)“主体思想”
0 {- L# ^0 f/ N# m
2 J  R7 u9 T; W        请参照炎龙工作室的《游戏中汉字显示的实现与技巧》这篇文章,可惜使用的是Windows API,作者千里马肝,上网上搜一下吧。
' r2 ]) N6 x+ E% y$ P9 t4 `& [4 L6 p0 M" _
        附带说一句,上面两条都是直接从这文章中剪切下来的,>_<  不要骂我啊,不知道算不算侵权呢。 7 w8 w& P# O! `7 D* j
  ?+ a7 i0 W; G8 M# p: F$ R: Q6 l# g
3.动手术---比你想象的要麻烦
1 o, M2 [. m9 I7 @(1)
4 V* e' p6 k7 ?0 h0 ?- g: \        首先要告诉字体类,我们下一次渲染需要哪些字。以便字体类可以在需要的时候释放不使用的字体。
$ I6 g2 D( {, y) H- Z  n5 X) x" x
0 ]$ |) _, B$ n        在Font类中~ 9 U3 ?+ t5 f- {7 ^7 i& A

) J7 Q* Y' _7 r( Y        a.增加数据 bool mUsing[OGRE_NUM_GLYPHS]; 用来标记文字是否使用。 1 c: \* {0 z: |4 z# c

& P2 A5 T7 B/ }/ _5 J        b.增加函数
  |% }# v: x) ?1 m! w/ B: Y8 m2 A; F! W, B
                inline void setUsing(std::vector<unsigned long>& caption)
  x8 Q4 h' _. `; J$ \  t" ?
( I$ ^& Y5 Z% l" y                {- _: i% V0 i2 `* E

3 Q2 Z, r  d! Y                        memset(this->mUsing,0,sizeof(this->mUsing));
( R4 K8 N9 {$ M2 k5 z  G* e9 m( b1 Y0 a. d# T% k
                        std::vector<unsigned long>::iterator it;% J, s& h7 w- r
4 ?& P+ |7 C2 R& Z$ R1 J
                        for(it=caption.begin();it!=caption.end();++it)
8 k4 @0 _( A' @
6 |2 L, U4 o5 A  Q/ ]5 O& d  e                        {  |$ I' X( ^. r6 c4 l" L
, E8 N* ?, f% P* f4 x
                                if(OGRE_GLYPH_INDEX(*it)<OGRE_NUM_GLYPHS)
( m+ C0 s7 _  }! _' X# ~  N; e  Q: v; X
                                this->mUsing[OGRE_GLYPH_INDEX(*it)]=1;//标记文字为使用 % O3 A7 J$ F  I3 ]# e5 N/ R7 i
1 I2 s7 B' S, ~) B8 k
                        }( H) L5 h' o- M/ w

; n* V% }& s; }/ u/ O2 i8 W: t                }
$ a3 u5 u4 R4 l& Z( m
& N7 ~: L2 s' c4 c        并在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。
; W/ r- P7 e1 Y' o7 F(2) 5 r9 h& Z7 Q3 @- R

, {- U& q# R  m9 G9 Y/ P& P% |2 u        然后是修改void Font::createTextureFromFont(void);+ ^/ I) \. k* Z

% d. l& N: H, \# W* X5 U4 }        Font类是通过void Font::createTextureFromFont(void)来把通过FreeType2分析好的英文字画在一个2^n*2^n的贴图上,然后再保存英文字的位置。 : Y9 I8 X( c8 U: a8 {; k& i& Q

' d7 B7 x0 A! ?, X        我们需要修改的是:
9 ]2 c4 O+ _, ?3 `# L+ g3 k) U- Z! S" `! }
        a.从函数中分离并保存画字的FreeType2和辅助变量。我们通过一个类来保存和处理这些变量。
+ ?! A+ x7 F! ]6 e% |- Z
, s$ e" C8 [2 K! q2 H' T6 z, x        class TTFMsg
3 N) X3 T  A2 [0 }( q$ F' U+ g6 e; r; Q: a4 [
                {
4 S3 Y7 h$ Z: I$ n# m
5 ]. f5 I) g2 y  a7 @8 d5 @4 U- w, u                        class Max//类中类,用来保存几个"最大",
1 d6 R$ \6 M1 L* a! f* q5 m" f5 z
                        {# Z& u5 D# b2 v6 R) b8 T( K
  ]; I% e: p7 ]8 R2 B8 d
                                int nothing;//这个是用来占位的,没意义,反正没他就运行出错,可能和数据对齐有关吧。
1 @5 X: C% O( O* R9 a' x( N
- \% I0 t" _1 \* H                        public:- [) R! o) }9 n) D* C
                                int height;//文字最大高度
" p3 R' Y( L" O" O. ^/ a: I                                int width;//最大宽度 : C0 s: p0 F6 h% L7 j* K7 r+ D
                                int bear;//最大空隙? 6 m# x9 \+ X/ U' O3 @7 l
                        };4 T$ w6 p4 N$ I+ G4 B5 M, L" p
                public:
  g9 W' ~: H. e- ]7 N. |: m                        FT_Library ftLibrary;//FreeType2用
' ^1 q' N7 {5 q0 j8 n4 k1 s                        FT_Face face;//FreeType2接口?
  z$ l/ S8 F$ F& c  H! a                        uint char_spacer;//文字空隙 2 s4 D# L; l/ s" T# T8 E
                        SDDataChunk ttfchunk;//数据块,用来保存ttf信息
7 x, X2 {# L+ y( [& ]# S                        FT_F26Dot6 ftSize;//FreeType2字体大小
/ \8 t1 F+ x5 K0 h9 e                        std::pair<uint,uint> point;//在位图上画字的点 ) W: Y1 z% Z: q/ g  B) x
                        SDDataChunk imgchunk;//数据块,用来保存位图信息
  ?. {( Q6 T1 I! D# a: u                        bool dirty;//标记,看是否需要更新贴图 + ]& r1 Y6 F) l: L
                        Max max;//几个最大
, ]3 s  {# m. S' r) z7 h- s! o1 B8 t0 f7 e
                        inline bool init(Font*  font) //这个是初始化函数在void Font::createTextureFromFont(void);中调用.5 Q; w* q; n) S3 O5 ^7 J% ]
- ^" [, C' {6 t6 T8 G# J1 Z  c
                        {      
* K" ~, g! B0 Y0 @( S! ~9 s- v6 W+ F) Y: m; Z
                                //以下都是初始化,大部分都是从void Font::createTextureFromFont(void);移植过来的
6 X/ l5 Y0 K% u& m
2 F0 `8 }0 S/ Z/ p. \, Q) E                                dirty=false;$ u% R' V0 I8 v; ~- `' N& Z/ j
* H9 h$ l1 m: h- L
                                if( FT_Init_FreeType( &ftLibrary ) ), y& g4 @& x  ^6 [/ Y; P
, k: ~3 ]5 i' v5 u
                                  Except( Exception::ERR_INTERNAL_ERROR, "Could not init FreeType library!",
( u! x& {4 A; Z5 I
5 _+ ^5 `5 @+ W                                "Font::Font");8 H( Y$ U! P# ?) [

: d/ W4 I' `% h1 o% m                . g# }2 k$ O. a) K: j) Z' S
8 a4 p' t1 W0 V9 ]9 Y- R/ y
                                char_spacer= 5;9 i* q0 w% |" z) w# g
/ [5 E1 _7 d0 \' m
                                FontManager::getSingleton()._findResourceData(font->mSource,ttfchunk);
- p) G! P' m& B) N6 T. }- z$ K9 n5 h; O% e
                                if( FT_New_Memory_Face( ftLibrary, ttfchunk.getPtr(), (FT_Long)ttfchunk.getSize() , 0, &face ) )
8 T5 M. W6 t* N9 i
& L0 n1 k' h5 Z8 M5 L                                         Except( Exception::ERR_INTERNAL_ERROR, ; ~8 d: D' [6 L" J7 Z8 F2 h

9 q8 L, ~( \! ~5 @' k4 U: h                                        "Could not open font face!", "Font::createTextureFromFont" );
6 z& |# A+ F3 i% F; e) ~! a4 h8 {$ k
                                ftSize = (FT_F26Dot6)(font->mTtfSize * (1 << 6));8 Q$ Z: H" G% S5 R8 H/ r

& x$ {$ U# B; L+ I/ C                                if( FT_Set_Char_Size( face, ftSize, 0, font->mTtfResolution, 0 ) )5 r. G6 Q6 H4 ]( s; J/ \- G) ~

+ R4 @! Y3 c& N& d                                        Except( Exception::ERR_INTERNAL_ERROR,
2 L( i9 M/ x5 h* ?/ T2 D* C* \. u, v- B1 y3 u7 J6 i
                                        "Could not set char size!", "Font::createTextureFromFont" );
+ V% g" D8 L- K4 h2 `
/ J4 S! P9 T2 M  
. T  ^* ?+ \9 c1 q2 r& \4 k2 b( Q" M- F9 M
                                return true;
- `! b7 i$ r' e' O4 S0 M+ C5 |
& l5 w0 e0 [$ R' s% x$ _# Y                        }+ d/ r0 I' k4 J

* J+ r; j0 n& d/ R  O: A/ j                        inline bool done()( Z4 a7 M& c3 R) a

4 b' D, o2 l$ f8 V                        {
3 a  b, ?6 d: a0 d4 Z, ?6 S
% T* K* W$ C: i8 `1 L, h                                //在Font的解构函数中调用的,本来应该调用下面两个函数,但是不知道为什么一调用就出错,不用倒没事。
* |/ l2 i: e3 ]8 u  ~1 B! m2 ?! _4 v% X! q: X$ ?/ S6 \- N/ }; a
                                //FT_Done_Face(face);% N+ k. ~3 ]/ k% m/ p( w" L6 H

4 U$ f$ p2 v! B. q5 f                                //FT_Done_FreeType(ftLibrary);
" h# V0 G0 Y/ [0 H/ D/ E$ |1 M+ T' Q2 L8 x* F4 n% P1 g2 p
                                return true;
/ W0 p( t5 _9 z' X* Q  m7 D, c. X0 n& y* t, o& \3 e
                        }
& i+ a4 L* t& P7 A. ]( Y4 Q, I% X# F6 u, Z! S! K
                        inline bool getRect(Image::Rect & rect)//这个函数以后用的,是用来找到可以画字的贴图的空的位置
# J$ S& i, }; ?6 C; l$ e: d
+ V# n" K; {) r. ^% O0 V( i6 |                        {
, x$ R; _% y9 `, u* y, _8 M( ?' w) q: L$ v' y4 f1 i8 O
                                if(511<point.second+max.height+char_spacer)
% ]) @& ?$ I: j- Y+ v5 a9 R9 ]
0 E+ M, H! f7 |                                {) _( {3 e* h5 i9 A3 ~. H! _$ D

( j6 R! k2 h, s5 D                                        rect.right=rect.top=rect.left=rect.bottom=-1;
6 K/ s- A0 \: d: w( w* }' M3 a0 I: x. v* X
                                        return false;0 i$ z) p  E3 t* E0 ~. ]) _

( _" ^) A8 d1 L9 Z6 F9 d1 \% {) o                                }
. w% d5 R$ R9 Y. v, X5 z- y; N& z
                                if(511<point.first+max.width+char_spacer)  f( ~/ F3 r9 @, |

9 ?8 t& m# I1 ^4 j6 I' T4 k. ^                                {% t( t0 o* q6 d2 h

$ g3 o7 x! w1 u' V9 C: @                                        5 d$ x% }& T1 }

% s! p( ?3 s7 c7 y- j                                        point.second+=max.width+char_spacer;
9 K' ~* _- q  K: H8 l( z2 _
1 {, v  T! D) ?1 U                                        point.first=0;4 N- T0 p* `9 P/ O
( S, e7 w! B7 ]! h, e
                                        if(511<point.second+max.height+char_spacer)6 s/ {$ A, I  t6 s8 c0 l9 E# n! i
9 c& ^& |& j/ v: t+ _7 A
                                        {
) }( p/ s8 p. X3 r# i, Z0 s: s1 f+ Q& h) D/ \
                                       
- E. a: Y3 o1 I( k6 m2 _1 i( j4 Z5 w5 z* M& N/ G3 _# y
                                                rect.right=rect.top=rect.left=rect.bottom=-1;
; w0 |; k9 r5 H, C% Q' w! K/ T6 t9 ?' d7 `/ n) T( e
                                                return false;
" @0 A" B( F+ C5 T; ]/ y+ n' c9 S" L) W4 C/ j! c
                                        }0 n6 L) v# e( I
8 E2 a8 o0 i8 Y7 n
                                }
. P( k# |  g. U& e- U5 U
7 o! J  q1 C2 E. ~1 K                                rect.left=point.first;
1 s' R$ S  s% [' h; o) h4 A1 u- J
/ o- r9 }" O2 }% N( U$ T4 g                                rect.top=point.second;
8 P( M# R! b$ J/ g  P) C: L  }* }/ w6 H# w
                                rect.bottom=max.height;  J7 R% p/ C$ p9 W

, I( u2 O8 j1 f" s+ z" C                                rect.right=max.width;
) p& u( u& [( Z( \- e' J9 e$ i6 g% g# B  o( G
                                point.first+=max.width+char_spacer;; L. O% A5 v0 {9 z" I4 C7 D3 t7 S
5 v: U2 F! c% w  Q9 s& h
                                return true;6 {; r$ ^7 J8 p9 H1 u; W; O3 W5 e
; z( F' y- U1 |  O
                        }) K: Q, c* X1 h& J
) |* x6 O: l6 z" C+ |- j* x! c
                };
  v" {1 `4 u' q& s, X1 j$ W
& C$ T& \8 _; ?& X% h' U6 f- G        上面的类定义在Font类中,在Font中增加 TTFMsg * mTTFMsg 数据,并在构造函数中 mTTFMsg=new TTFMsg;
7 y! L0 q/ S+ \, u/ ]4 |4 c4 t2 ?$ J( f9 l" W+ E: R
        
; r( ~9 ?# Y% U- g3 Z. o5 M" i0 G' i+ S" u5 D/ Z
        正是修改void Font::createTextureFromFont(void);函数,主要几点,首先是分离出很多变量和构造到TTFMsg类中了,然后是贴图从2^n*2^n变成固定的512*512,为什么要这个数字呢,因为256太小(废话了)。能保证512*512大小的文本区不会出现不够画字的情况(所有英文+符号+没有重复的汉字),这个安全区域基本上是够用的。(什么,你要画满屏幕的汉字?哪你自己看着改吧。)还有一个重要功能是,要找100个汉字,找出最高和最宽和最大空隙作参考。修改完成这个样子了~
5 P! N1 ~! }& V) W+ E, |  T5 u& f0 L0 ?5 V! U
    void Font::createTextureFromFont(void)
- P9 r% `. Q$ m* r& h1 m+ A1 W! l6 B
+ ?' b7 X# j8 j/ R( U/ C% E$ P    {
* t- J  H0 y6 Z$ _# v, N  Y) u
  E6 X0 q( U6 V' {0 T        mTTFMsg->init(this);//初始化FreeType2) y& C# Q! K5 }% A5 q) I9 M5 c9 Q

& ^' [% f  S% i        uint i, l, m, n;) ^4 n6 _* V0 ?& \7 n. L7 t
1 h" @. l- b8 G
        int j, k;
' e2 C$ d4 ?, X3 D: T3 U( l& D9 y: J# [. i$ C' c+ Y0 X9 U
  
. u" n5 Q- C5 L) }) I+ ~) }; J: ?5 p) h
       ) L! m8 I; ~  k+ c$ |

! M/ p! B, R/ e7 q* P+ [8 L        FILE *fo_def = stdout;//啥意思?我看不明白 : Q, j& q- `8 ?/ Z2 R' n" `' Q

* w$ C' X  L  y! I" k3 ?  
3 R1 I- x3 n7 F7 Q, y+ V5 I; F' r% z& l# |0 g! X
        int max_height = 0, max_width = 0, max_bear = 0;2 ?+ z* x: h1 x; U* x; L! H2 V

& V4 V/ D3 l2 R$ @4 m( J  $ @5 A. }* m% z- Q$ \! y
! Y: R# g, J* s6 \& A3 [' }
        uint startGlyph = 33;1 e/ a. v9 o  Y: B

3 s. R" W9 y: ]* W        uint endGlyph = 167;
& A: h% ]3 j7 @( ^
# z% m5 G! Z( a/ u  
) V* m, R0 O1 s$ D, R# g! q
9 [* N5 w/ ~- F7 N+ ~- P        // 找英文的找出最高和最宽和最大空隙 0 E2 ?: E/ W' W" \

2 |" C: e9 i4 n6 v4 M3 Z        // Calculate maximum width, height and bearing 4 J, H2 s  V- B
7 `: P3 a' J4 ^% u( K# k
        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )
4 Z; R8 c4 Z* z5 w5 v) [" a6 X6 D. |0 n3 h' v
        {0 J1 {* U$ a8 S, ?9 g9 |

* M) T1 ?! ]6 `! q; @; \8 V" \            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );! x, v* k6 e2 Z) ]$ e$ T* w

2 ^$ s: X& M, l3 Y            //以后的 <<6和>>6都是FreeType2中的数据和我们使用的数据的转换
3 w! d' z7 V& ~5 k6 g+ h" e
  ]- u4 n/ ]8 l            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height ), R! d/ \$ f2 K5 f) _7 @
4 }" ]; ?- s8 Y' w9 e5 v: d1 O  ]
                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );
+ Q/ y# e9 Y- M8 f& S, @; c
4 A/ F2 x3 Z4 ?3 O" F2 \            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )
# L4 N/ K; p. y, J- y, p4 t5 R. {( E5 m( J1 F
                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;  T4 {. R4 L9 I9 ?

, l: p/ A$ r% m% X3 Q5 m. {  . r( y( {- m  G
2 ]' L. v: w. y* c. x+ W1 a- W
            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)
5 p6 V5 f' d+ a. S3 T
- e) v/ Y& a% m2 ?6 x  L                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );, c0 F8 s: N4 z" A0 J

/ u9 h. N, y# r: ~0 [6 E  o" R        }
2 g) I* E2 C! k3 T# z! v; _
% J$ R) a9 t' b  - }5 w& K# B" \9 J. A  ?

# ]% }8 \- A" N: E  n% g  
1 y, |; p" w2 W. \9 R) X+ F/ W& w! i$ W) k' Z* U0 a2 b! G
        //下面的for是找100个汉字,找出最高和最宽和最大空隙作参考。姑且认为最的汉字就在这一百个里了。 0 M1 \4 K4 H$ `+ q6 f& b1 F
: l! K" o1 B$ {( ]! z
        for( i = 20643, l = 0, m = 0, n = 0; i < 20743; i++ )
$ k8 E: U1 F  H5 i$ V' t; o9 x+ f/ U
        {: Y4 q+ g/ D% Q" [% t* v$ A

' a( M0 @( E. u' I2 U            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );
1 L3 k- U  [/ A7 y
! u5 u7 G8 D  w; ^. q' j2 f  
, o' u5 \1 _7 r7 T
5 p( G0 X8 @6 h            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )+ u* s0 f1 ^5 r# J% l- P
" U) N. v0 z" _" _0 P
                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );& V% U1 [' d. {4 G9 U

, t, a' V9 {5 q5 }; g; A- D: R            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )8 X' j  m/ Y+ z( Y/ h( y

1 s* X' @4 F# I& w: a                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;
: e) `# P  O/ |5 c) O5 B# A$ @$ ^. `. x! ^) `- ~
  0 L' E8 u: I/ g7 H, a1 y: L3 E9 @

2 Z4 q& f* M0 }! v3 i" G' t1 k            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)
. C$ m7 {; P1 G3 A" d5 a8 ?+ O+ E# U
                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
8 F  m, O# \! y# C% K' @6 B0 K# d+ \
  + \2 |- S( u1 V# W

. m/ i; w, t$ v9 Q/ g2 u. p                        $ K4 W$ B" C  n4 R( Y1 T+ \

1 U. U+ H1 y0 t: @            if( (mTTFMsg->face->glyph->advance.x ) + ( mTTFMsg->face->glyph->metrics.horiBearingX ) > mTTFMsg->max.width)1 l) T, @+ g+ i
' j1 _3 F) B" ~8 ]# [
                mTTFMsg->max.width = (mTTFMsg->face->glyph->advance.x  ) + ( mTTFMsg->face->glyph->metrics.horiBearingX );
% N  O' ~, Y6 B" l, l6 n- p* Y0 Y
# J% O+ `: R$ f( k3 O' [        }
% y& @1 U  U6 P" N2 s' I5 |6 l0 \% A. B
  
; D- I4 _: E9 _/ u+ U. j0 A5 {- _* z
                //下面几行行不需要了 我们要512*512
5 L( R2 S% L( n2 g
+ h% P  R) M1 y$ ^, b                size_t tex_side=512;//就是这个了 512. K1 r2 H$ U  {* b- J/ u. @6 _
& }1 E. k8 B8 a9 G7 i
        //定义数据宽度 因为是32位的位图 四个char为一个像素,为什么要位这么大呢,难道不能用8位的么,我尝试着改来着,不过改了之后就不透明了。望高手看看能不能改。 5 ?7 X/ K0 t# G, x
/ \: `+ Y  v& A3 Z) y% M: N
                size_t data_width = tex_side * 4;
1 |5 J7 ^8 ?7 |7 R4 q3 a
( |6 i+ R- @2 Z2 s/ |  
4 v2 D$ j) O2 R8 Y6 t) ]
8 k# o& {/ t6 I) o; f# {                LogManager::getSingleton().logMessage("Font " + mName + "using texture size " +0 c4 z* B. t0 o
  l* ~, n' a; F( ]
                        StringConverter::toString(tex_side) + "x" + StringConverter::toString(tex_side));
4 F3 }- s1 F5 N5 ~/ u; p
5 Z+ ?  S% }( `5 i8 m) C  . D1 }5 T4 W( d1 i8 Z, I) O

. ]8 y4 g8 g. w; S* J. L        uchar* imageData = new uchar[tex_side * tex_side * 4];//设置一个空间用来保存位图
5 k3 a" e( n) P. k- \6 @1 e
+ j- ?! n4 ]7 {- D* ^  {1 L2 h& I                // Reset content1 q' x1 I. m) g* E( e. R# A

0 J& {- j- `  E  d                memset(imageData, 0, tex_side * tex_side * 4);//清零 / P2 ?  m- |4 V  ^; y" y" z

2 V* U5 {( C4 [( q$ F0 _6 ^  
  e: v! j; D- g# s4 U
: k) i$ c4 X/ M' u$ A        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )//遍历每个字, - `% k# P6 l2 v) h7 z
8 a9 q$ k# u2 }
        {2 X* G' E4 t# ~! |
" f. i4 K$ I1 u* y$ T: V
                        
9 H! V% x( t( q3 B! l9 [
! |! C4 h2 C. |4 Q' C; N) l            FT_Error ftResult;
# i, ~' x5 G: h1 }- _* D. o: C! J; ]+ L( b! q2 Y9 ]
  : B1 r: D0 h8 m
( m6 \, d5 M: Y# ]. Z
            // Load & render glyph
2 ~- s2 r, R. ]# K7 e9 e( S
$ m) H  z* Y5 z            ftResult = FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );//读取字体 % Y( ]/ l! ~5 x! n7 {' V& m

' r2 R" C2 t2 I  C! M- V7 t( i9 d            if (ftResult)
% U( K" R& L- D; j" S
0 `2 k" ^1 ^/ R4 ]5 T            {
6 h9 I/ R: R9 s! ^
) N6 i$ Y& O$ R' u0 A* R- H6 R                // problem loading this glyph, continue
: ?, s% z' m) D. H
( D3 l7 ^' E$ T4 R                LogManager::getSingleton().logMessage("Info: cannot load character " +$ m+ C+ R! w" W1 r' v" @4 I
9 c* H: j/ Z& a3 [, U
                    StringConverter::toString(i) + " in font " + mName);
, |- ?) J) {: [% w9 X# C  s6 r& K* Q$ H7 U
                continue;//如果错误跳过
& r  B, P' {& `; Y/ P$ x5 l5 _# X7 ^7 k9 a+ H& }
            }8 E5 F( N6 O" y$ h7 \1 z9 [
" \: o% w& _+ G; m% A# L
  # {; {) ?+ w  {' h& A, q: ^
8 J6 c- T& N9 T6 N9 z
                        // 应该是字宽
3 ^. @' G+ E5 t! f. Y" W' D9 h& i, ?9 R# T0 B1 e1 m* X
                        FT_Int advance = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );& n8 ?: @4 s- y2 ~' F6 l/ d* Q' `
; U: Q2 B* y! Q5 t
                        4 [# A4 n: F" m% @* w

$ _7 p: [; U, c$ h) M6 v                        // 得到FreeType2的位图 7 {/ R4 Q4 c9 z8 i8 g
& g7 ?0 V1 g0 D
            unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;
* ]0 p0 _/ \- S( ]0 A  w# _' z2 o; P' p' S9 m/ U
  
* s! [' k" I* \, A; [7 R( e5 _6 H, U9 D% ?, r. Z- A
            if (!buffer)9 G  U# a$ _8 d* [

+ D6 q0 r- K5 d5 g: v' V& r            {
4 X' d" `9 J, }/ z- q2 @1 D: t$ H. J$ W* X( W3 u' K6 v5 C4 N0 \
                // Yuck, FT didn't detect this but generated a null pointer!
' {0 b  B8 p$ P, r( F+ d
$ P3 v7 I. u, Y# |6 f+ d                LogManager::getSingleton().logMessage("Info: Freetype returned null for character " +& E! {/ A0 Y4 {: ]$ H
# g0 A/ i* P, z* T5 e1 S
                    StringConverter::toString(i) + " in font " + mName);6 f  x! t0 u9 {1 X' x  Q

- l# o! ?6 k' N* X7 t7 K                continue;//如果得不到跳过
& f2 E1 Z  b6 [* |' k+ `/ `
  X! g9 {* x0 t0 q9 R1 k/ H3 G            }
- r: M: ~; H% @% i5 `
6 h* r; ~& y( a. P5 h  
, n$ ]* |0 e- Y
7 \1 c  k+ f! X! {$ {, y; X+ Q# w                        // 得到y的空隙 (最大空-空-本字空)就是说空出这些字底部就平了
3 a' C# g9 p4 Y2 R) @+ ]% R
$ ~, Y! a- f8 M. l            int y_bearnig = ( max_bear >> 6 ) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );; C, R6 J9 M1 Z; t& e0 o; x
; T3 b) X% `  r7 [& N0 m' M
                        
2 q6 H4 t, N, w# o& C% [' T/ C2 q. S! H6 f5 x. j
            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )8 d' F& v1 v9 F/ \" h! H

" Z) x6 Y* l) R, t            {
1 o" z# f5 ^; `. P" ?$ U# L9 w, w" I) N/ U
                                int row = j + m + y_bearnig;//相对行+本字在位图的总行+空隙 / N; f( ]8 {1 R9 ]. h6 y& A" f
& W8 k* h( l* i3 U2 n
                int col = l;//列 : ~% G7 C& ~) @( c
7 H3 N# n* g( L4 H- [" s" H
                uchar* pDest = &imageData[(row * data_width) + l * 4];//找起点   & C! S) g/ F" a' \! R4 \, H

/ h% g! w3 I4 A                for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//画图 / K/ X" l1 }% `8 N) z7 ]
8 |1 g1 v% o' q, n: e9 Q
                {$ A7 d8 V# N4 N( _7 j4 A
! }' x' Y3 r* |2 x$ L* @
                    if (mAntialiasColour)//看不大懂,难道是灰色字体? : G$ W% V$ n- E. k
3 Q* ]9 B1 q) N7 B
                    {
  V/ M+ u# X% t8 H
' }& X0 l3 O" B; _                        // Use the same greyscale pixel for all components RGBA 6 L2 @# i6 ]( M( n$ ~

6 h, M2 Z; Z) o3 A% t3 c, _) x' U* n                        *pDest++= *buffer;
, N7 d; e1 U' ]8 ~. l
) v" D2 A# M9 Q, j3 ^                            *pDest++= *buffer;
6 _9 Z, O9 n. U5 n0 r. |& _+ h  R# o6 P+ N/ \1 b
                            *pDest++= *buffer;
' A  m2 ]! c4 s$ M4 Y9 t, n
  {7 d5 j1 `; X5 \8 w                    }
8 R' E0 ]1 O7 n2 e9 Y% x* R! h8 y, ~% c+ a
                    else
: c9 D$ i" g& t6 F6 q
5 q- N6 h3 D( }/ ^, Y1 M                    {9 e! }; E% `: @$ X
9 N* l, T  v7 v+ P7 y( t
                        // Clamp colour to full white or off / q# \& m* ]. l( m

* F, z% o' J2 T8 ~% J4 I. w8 X9 l                        if (*buffer > 0)3 ~; n# ?% \% v

( H5 W) N: c' F7 R8 ]1 _                        {
0 `  q8 `! _9 b/ g3 U7 }0 S" z; d& u- M" G3 u6 e
                            *pDest++= 0xFF;
) n9 }) Q& v  R# u$ b  ~0 Y( G( D, H. h7 L0 Q
                            *pDest++= 0xFF;
' f8 Z* R0 W( J( t' @* ^; p: Q' C9 x$ p  {
                            *pDest++= 0xFF;
! @- T0 R6 c/ h% E2 I  m) G% h0 s; R3 H) _; e0 A* R
                        }8 u4 X, Q2 R+ E- r4 z  d% Y
$ C9 g7 f! P* X
                        else
5 u; b5 i8 l6 i( o1 k8 ]5 C8 O8 z
$ [3 X! I9 I; Y; }                        {; I; Q1 p2 r! l

0 v( N  a1 b, @& g0 ~                            *pDest++= 0;
( T, Z) u& Z7 x2 S" Q
" j% b" n0 A/ ?2 L+ E, m                            *pDest++= 0;* v! a; M6 ?+ c7 _/ o$ w: u

* T, o% J. w5 a6 G                            *pDest++= 0;
, L2 R) C+ o( j* k. J; x/ l! t% m# x% ~3 f
                        }
4 A8 r( [; \7 _& R* p, W" x' Q% t1 p9 _- h, K
                    }
) M: ~$ m2 \0 @" M! E, q! C( A" n# S+ E) e% K. O9 {9 r
                    // Always use the greyscale value for alpha 3 D; E0 v% Q# L9 j0 {: r

# L% H  s1 L7 w) s7 k5 T4 Z6 S                                        - a4 @' o6 M, o, m- z1 w/ b

3 b/ W' j# U- u# ^                    *pDest++= *buffer++;//alpha! 我是一点不了解了为什么是这个? # L. D  e3 \1 O: A3 w* z$ B
! [, \( b1 v# }& M5 |* _( j
                }
/ |. J( S! Y& ]. u7 _. j
" q1 {, e4 F+ K$ b# c- M* H            }
0 ?9 M$ p- J0 d- A
" c1 a5 X5 p2 w7 T; F  
! l8 P0 m4 A1 d( c, j8 Y3 M$ p/ D  A! [3 Y8 ?
            this->setGlyphTexCoords( i,
7 f- i) W8 L" u- x  A4 D+ F
! z2 t! V" t+ D0 S# |                (Real)l / (Real)tex_side,  // u1
  F+ B4 a( T' j* A! a
7 t! ~8 ^* ^% A+ `7 h/ ~2 I# \                (Real)m / (Real)tex_side,  // v1% k( e) Y. g6 v5 [( @1 h) M- |

0 g  A5 o$ C. O4 v4 z6 X0 j- N                (Real)( l + ( mTTFMsg->face->glyph->advance.x >> 6 ) ) / (Real)tex_side, // u2; Q; P3 X; U2 i# b2 f

( C: j: k, g  p! \  ?. i8 W                (Real)( m + ( max_height >> 6 ) ) / (Real)tex_side // v27 y& l0 ~4 h' {! n! S

; A2 u. L0 E6 n8 K  R' Q; ^# A# Q                );//设置坐标 1 ?( Q! S" |( F

( m3 s/ C/ J" X% ^: v  
. V& W6 z8 |# J5 j& O: ?* N
0 H$ v( J! E  b0 S: b9 t+ C% j0 F            // Advance a column 8 ~; Z$ j9 s, m7 h! h! o8 R

& F0 y6 ~7 Q' H7 [6 U5 P; I            l += (advance + mTTFMsg->char_spacer);
  ]/ A% f* ?9 k/ k" j7 n( P! ~/ p, y  N0 |  g/ x+ m
                        //l+= 本字宽+字空 8 s) U8 _- \' r* m( l

- h# u  I& h3 B3 U' v$ p  
) A/ b4 ]/ ?" ]& K; i9 l
* V8 _* \5 a0 N& Z            // If at end of row
) j) v: \- T/ o. n4 G" p4 b" h: L
                        //如果到头容不下一个字
$ W* t' I% h( Z
3 _( e/ T$ _5 ^* T! f) O! d            if( tex_side - 1 < l + ( advance ) )
$ v9 {$ Q& a/ t: q  H6 Z! M' w, i2 e2 F
            {
" _" q; H, B3 b
; i3 ]3 m3 c* L, y0 I9 p5 X                m += ( max_height >> 6 ) + mTTFMsg->char_spacer;8 \% G9 Y4 x8 {8 g% I5 w& W4 b

7 |: S8 h$ w9 C# a+ m) }                l = n = 0;  P1 B& S- [; [' k: Z0 w! Z

" y. N0 t) [# d5 z0 N2 a            }
; B. X4 |9 M" n; Y' b1 R. X! w4 U% B2 J  i9 l
  * H" h; J) k0 x6 v: t

7 m, J8 @* f  Y9 f( k2 f9 f' Y* t, e        }
; [$ N$ \/ Y6 \; m8 ]9 C
% v1 K  F! \2 ?9 }7 _, ^                // 把信息存到我们的mTTFMsg中 >_<+ d, J: ]# N+ |* @

. o8 t/ b3 o! J/ }. R                if(l)& }+ f2 a6 \; o4 b  o

! I2 K9 h+ ]0 j! T5 g; Q                        mTTFMsg->point.second = m + ( max_height >> 6 ) + mTTFMsg->char_spacer;! s( T& B7 p/ ^9 j: c

0 z+ Z; H* l2 h) Y+ i6 t                else
5 n9 m% E# e1 Y  j/ W% W
& ?- Z" W5 F) |* x  [' }9 K                        mTTFMsg->point.second = m;8 \  h( \, ^5 X( M" q
. N8 S  J2 V9 o: M- |& s2 f3 l) F
  3 b: ^, s( a( v6 Z! E0 R) l
, B/ r3 I- y3 v' x9 W. t
                mTTFMsg->point.first = 0;//另起一行 + [0 @' e% P! A, p: a
# O/ @" v  a8 G' B, K
  
/ t* b  v$ k3 a( z$ w7 X4 `# O
) f+ ?4 Z0 O0 C# Y& X2 \& ]( i                //下面是保存几个最大。
. c1 J4 \0 Z) d0 ^- s6 u6 H: a4 t4 v" S
                mTTFMsg->max.height = max_height >> 6;
8 \, t0 D  E( v- y, G. B3 v1 H9 M9 U$ R  ^/ q
                mTTFMsg->max.bear=max_bear >> 6;6 J. u: N3 g) w% S! |: D

8 s- U2 }" W  M: p                mTTFMsg->max.width=max_width;
2 k4 U. h, Z/ Q( y4 j4 l! W; P; ~; T( O$ N) W3 R$ a- T
  ( V) R: q: F8 p7 f1 h. S- B

1 b+ D- }( ]4 `- G% X* _& f) S2 x                mTTFMsg->imgchunk.allocate( tex_side * tex_side * 4,imageData);
( O3 t5 o# u: ~
4 T) t! Q$ Q) r" y! y                : i% E, {/ {6 |6 x+ W  M. B

9 k* v: c" n7 }                //不知道为什么要设置img这个中间变量,似乎可以直接从chunk创建贴图
0 ?4 z1 _. a. e: Y5 g5 \9 D
# \% ^! U7 P) b        //--Image img;
0 ]: H- p9 k( ~- c
9 u$ b( ^& n; F# M. e, w& E                //img.loadRawData( imgchunk, tex_side, tex_side, PF_A8R8G8B8 );
8 H- m  Z& a6 m) V8 R$ U
7 k- B5 Q0 A1 z% B& T$ c  " j1 U) L- }# @: u1 G7 E, @
3 F: e- y" u6 c1 b' ^
                //贴图名
3 {3 ]2 X4 h7 n% j7 B2 x0 S; g+ _& c5 d, G
        String texName = mName + "Texture";
5 L3 B$ D) \, E8 K- F7 k+ j2 _' }: M6 u+ p' K, T% q8 E
                // Load texture with no mipmaps - g  ?7 U* L6 Q) r- y7 ^6 g& R

- b* t2 I+ P0 v+ S1 W9 w" c# z        // 把从img创建位图改成直接从chunk创建贴图 9 ?8 ?  K* x3 o) P0 r( i
' j) w% v% E- k+ O
                //TextureManager::getSingleton().loadImage( texName , img, TEX_TYPE_2D, 0  );
; n* t" b. k. A+ T9 p6 A+ o7 s3 s
                TextureManager::getSingleton().loadRawData ( texName , mTTFMsg->imgchunk,tex_side, tex_side,PF_A8R8G8B8, TEX_TYPE_2D, 0  );
6 \+ u- R. I% E/ U) q2 d
& ^1 j6 o* {! k4 u        TextureUnitState* t = mpMaterial->getTechnique(0)->getPass(0)->createTextureUnitState( texName );
+ Z; R& ^  ~5 I2 b- x8 l0 \. b1 Z3 O" p1 ^( Q
                // Allow min/mag filter, but no mip * S5 t1 z5 {- o, \% W% f, ^+ _

/ Z/ Q3 A+ Y6 u4 D8 @                t->setTextureFiltering(FO_LINEAR, FO_LINEAR, FO_NONE);
( N& O% m/ K7 o9 W
: \1 L8 q) G% @& V- ]& v        // SDDatachunk will delete imageData
, I9 C* t+ I* `; ~' ]
$ C. p' l# P' A# c9 m        
$ ~% s+ N* I; D, y% K2 K: D( ~8 u8 J+ i
    }
) o5 R2 d1 P% m8 ?: }: l5 e  }9 Y! M; E# k
        你应该对照一下以前的函数,改了很多的。 0 P) l  Z9 R. P+ _7 Z/ A; e( u

1 u. E: F. U: ^; a; `' n  . F. `+ f5 ~( Q6 z4 L0 V
% C& P! `4 ]- d$ s  q& L4 C1 X0 O: h" E
  , _6 }6 Z8 {9 M( N. m. V

% N! K* \1 z8 v+ g(3) / |4 {- Z: n6 @' E4 y0 o
! ]6 T; S. v, I
        然后最重要的是动态的申请和画字。 7 n8 H3 W5 i, l" Z9 L( q) T( x
+ o5 W% Y) R3 a( @! V
        首先最重要的是我们要一个方法得到汉字的unicode码,我们用到了unicodeMap数组,提供了区位码到unicode码的转换工作,等一下提供这个表给你,好不容易从网上找到的阿,可惜这个表没有中文标点的对应,如果希望支持中文标点,就要努力找到unicode码并加进这个表了。这个表是这样的 char c[3]="邸";unicodeMap[94*(c[0]-0xa0-1)+c[1]-0xa0-1];就得到邸的unicode码,不知道为什么没有5165~5169的unicode码,是轮空么? " N1 A) \+ K6 U9 \

' n% n: U+ C3 S  S        
2 N9 W, A/ e# E/ d2 q9 s% C7 Y
: h9 Y. t* q. C  o' B        申请渲染(字) & o, \6 b2 C% W5 z: I

1 b! L( Q. z( B( M        {* s0 V" U$ F' G! r0 y* `9 ]
! }2 _5 ]9 l  x2 S+ t5 g4 k
                if(有这个字)' ~+ {5 H$ j  X1 A7 D

9 |( `- l  m! q# m. r& Z6 ]" z                        返回位置
3 e6 @( p; c3 N- N/ f- Z
: z/ C6 O7 w" o                else
- C7 S& H0 R$ @9 z& l' d
4 ]" F- q# ~6 z6 d2 \( L                {& U6 A+ h+ n7 F

- [! Z0 ?9 p$ L# e                        if(有空间)8 N. U, }% e7 ?7 m  l/ y

: E2 M' E" ?$ _; F% a                                画字
/ @- r- U7 p8 y. X7 m* Y
. X2 y# w; Y' u2 u( r. E  D1 m- a                        else0 N" l( F( E, j9 @3 E9 D
) @, f: j$ E! B5 y1 h5 u* h
                            找不用的字//找不到就出错,没地方画了 . q. q( [7 x9 s/ @4 ~% S7 H
) Z0 q$ C8 {- t; a( g! W
                                删除 在这个位置上画字 7 ^% k( t1 _9 y& R/ x
! g9 l: C) C( u. ]8 z
                返回位置 , l; S$ e) g6 W7 y8 J( [3 V" r
  M6 T% z+ V& Y' O7 n  }2 |
                }. p; w8 V0 s9 [% R+ b
' x8 W8 N8 `0 \! w8 P' X& v. ^
        }
& Y5 T! p# ^. ~1 q
  M& I/ S0 {; Y6 R: H7 v1 l- _        上面很直观把,大体就这个意思了,申请渲染的函数是inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )  const。去掉const改一改。得到
) I3 E* }; N* W' o) j! X
9 M; Z) P5 x0 {" l        a.申请渲染
5 b5 o/ P# Z; i" e+ V
$ S9 z) q2 |1 O6 N* ]( T        inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )         
7 ~% s- C2 I" [! C' }, B* j, H' v2 i- c$ U! Z5 R. }; z
        {
3 Y7 t9 Q- R$ X5 d0 C
! A/ s+ |, H) a" z+ V: n                unsigned long idx = OGRE_GLYPH_INDEX(id);* ?- K2 R- g. m4 l* ?9 b
  h& X+ O) n2 _
                if(this->mType==FT_TRUETYPE)//ttf?  ^! y5 w# |8 z, f0 c) U% Q

/ I: C) I8 r  }                if(id>=161&&idx<OGRE_NUM_GLYPHS)//汉字?
" H1 ^( s# k8 E: n/ H3 J
* r. @" ?- s' ~- \                        if(!mTexCoords_v2[ idx ])//没有?
+ s* u( f4 y& f
+ A  k1 T/ o# B1 @8 ~# y  Z                                setChar(id);//画字去
+ S$ K3 V3 x, \# d- W2 Z
; b4 k( T0 `# z4 d             : n6 [  a6 H3 I) W: c+ @* p

2 ~: W; V6 g& q5 @; Z            u1 = mTexCoords_u1[ idx ];) `8 A! N5 i3 H" h" U( w
( k* l4 j8 L& y
            v1 = mTexCoords_v1[ idx ];0 v! A# `+ q# x' X" s# C8 p3 q+ k

( [( K5 `" X& ~( Q9 r+ }- @( T            u2 = mTexCoords_u2[ idx ];
, Q! f6 V  R- t- j" x  t* s4 V# e3 R
            v2 = mTexCoords_v2[ idx ];
1 d+ `0 H. x8 Y3 O; d; O, F6 Z
5 U6 b) X! n2 c  [& G8 T( g        }( D# |4 T4 q0 J4 [8 O4 _3 n( d
" P7 T! L8 q( L8 f: b- P
        b.画字等
; d* K+ W4 j5 ^3 J  n4 V1 E% B; Q8 q9 o9 {: W. E/ n
        bool Font::setChar(unsigned long dwChar)7 r8 h! A" r3 q: U
1 M. q0 A) t* Q! t& }# j
        {$ w3 H% F4 @( ^5 G1 c

/ L. V8 Q# Q! P0 K: g                int j,k;, b9 L* J* X6 b

' L- E! p: i2 u                uchar* pDest;//操作数据的指针 7 @, A3 ^( {6 t

2 j/ x$ ^1 @( ?2 N$ H                mProportion=0.8;//不知为什么,总觉得中文都太扁平了,所以设置这个参数,在《让OGRE支持中文》中创造的参数 1 V$ g5 y+ Q0 P7 n5 B0 z

! V  q- `) d( ^, Z3 a" J8 Y' K                Image::Rect  rect;//画字的位置 4 ^6 U, r. i( L
! I2 y  N  \% E# W( c; t
                if(!mTTFMsg->getRect(rect)/*回头看看这个函数吧*/)//如果得不到空位置
+ o# o- c( ]) \# s9 }+ T' n
4 S! e/ i  g+ J7 ^                {4 r6 s3 |3 C6 g5 l5 A! B

. z* ]1 {: P" o& @/ M                        for(int i=161;i<OGRE_NUM_GLYPHS;++i)//寻找不用的字 9 }$ S- i' K9 e) L& q

, A0 h3 p8 p$ q3 j( `" o0 |: C! q                        {: o  t# f6 o# t1 }9 Z3 z: ~. z
$ _+ A) W( S9 Q% @
                                if(!mUsing&&mTexCoords_v2)
! N0 ~/ u1 b+ A: U
9 a: Q9 d. c2 F: z! }( Q                                {
5 `4 _; y6 w; ^8 ]* k6 I4 Z" Z1 t5 p8 b# m* @8 g8 h5 m+ A
                                        // 得到坐标 , Z3 N4 T1 W. B) x" ?

2 m! x+ H0 u' G                                        rect.left=mTexCoords_u1*512;
* Q+ o/ Z* [+ n- H3 N0 l( t
1 g$ u4 m0 t' |) l  O" v                                        rect.top=mTexCoords_v1*512;
7 v8 h( f: s. f" M
% w( i9 B3 E7 c& _                                        rect.bottom=mTTFMsg->max.height;* y) b/ H) }) ~6 Z) C: U
2 p; k+ D" T; L( P" i; ?
                                        rect.right=mTTFMsg->max.width;
# F% Y( P! O8 p
8 n8 n! P" s5 O1 K, H, u2 \) G  0 T3 u1 _1 f( R7 b2 B
( w( R  \& {: }( @* Z
                                        6 y: T% ^+ c! |" W* L9 l' J

- V# O- \# j: E+ o+ U" u2 [$ S                                       
3 \4 h; a- c1 T) x' E- K* t- J/ E& A! ]. H
                                
) {# a) \- {; t( d7 R
2 F% S" }3 a- B9 B8 c$ j                                        //擦除(这段代码没有试验过,等做完输入的类在检查吧)
1 |+ K' [. L' W3 k5 E# ~/ a$ q4 |! g9 g/ G/ `: N( A  ?
                                        for( j = 0; j < mTTFMsg->max.height; j++ )
; ?. ?& h; Q0 V% R4 t; K; K8 x
% N+ `& d0 R1 [, k0 Z& w- _                                        {8 ^: X8 o/ d! T4 v' L& ^+ e$ U

4 R1 ?8 `9 R# a* g5 k                                                pDest=mTTFMsg->imgchunk.getPtr();
5 Y* {5 ]  B, u) }( y1 o
: s( |' \, p! @( S  V0 ?                                                pDest+=((j + rect.top)* (512*4)) + rect.left * 4;% \$ {: ]. k# i* `$ i
4 T# s, {# S' y# }  @! B3 k
                                                memset(pDest,0,mTTFMsg->max.width*4);; O% W8 W: D! |

7 z! M/ g: Y. q- B7 e                                        }
9 x' v- j+ \" O4 s: R$ i3 w, y- s  Z- k/ r- U% H4 H
                                        mTexCoords_u1=mTexCoords_v1=mTexCoords_u2=mTexCoords_v2=0;
% M" {# ^( W* I- F. x- A1 U  q+ |% H
  
/ c. B: o* c) `6 U; T1 c% o; Z. I* b0 n
                                        break;+ c" @- w  \1 o4 t  p

6 I% B2 N! t7 s' g7 b. k# a) x                                }6 Y, u0 V" B( A& J
; }& [* b/ p0 p( _
                        }0 W; T* P! ]  |5 h

8 c0 P# n4 R9 _. k4 g                        1 P; s2 C7 n: t( u; x6 K" r
. d/ i+ b- L$ Z! z+ G1 K5 }8 A- O- t
                        if(rect.top==-1)//啊啊啊啊啊啊啊啊啊,贴图竟然都用完了,没办法了,出错了
4 P8 g) B2 E8 m# D3 Y& L
  E+ w# `- `& U- f6 d* D                        {
. r" z& B) s. `! B8 P4 k0 V
; B8 g. g1 \- _4 L* M) i6 K  a                                LogManager::getSingleton().logMessage("你太贪婪了,用的汉字太多了,这是对你的惩罚.");
, _8 b$ J& d  u7 v+ i/ l" \
9 R/ _2 r! f: W! R. K                                return false;
- k3 u2 H' \/ ]5 R$ `
# G# _5 T$ p0 E# P  E5 f                        }
- ~7 \' ^3 ~" y# N% U6 [& C
* i, D7 D# s0 h# s! }5 o6 ~6 @0 H        3 b% A9 C* D0 f& p. C. Y/ B

7 s  j1 V  O8 U8 {9 j                }
1 Q& |0 o/ d/ c* ~- _* g
6 U* X8 `# C) C, ^5 s' N                        
1 {( U* x& t2 ~- d. W" f
' u4 f+ N; n5 Z               
! `5 |' f0 f4 q1 S: }" T( I( v" t. v) D8 z$ w$ a
                  //以下画字的都是招葫芦画瓢的, 7 R2 U& @3 v, X( r' ]- W5 F- U

3 U' ^# {$ w: R; i( h: Y$ d  P! B                  FILE *fo_def = stdout;
& n8 O! z+ z3 B7 T5 Y1 I' l# H, ^; \( d5 m# n: \1 r
                 FT_Error ftResult;
8 @# J9 N9 |' t: N3 R3 a# y2 T2 s  M7 @0 b1 D
  / A4 K8 Z* `( @$ G) b0 I: b0 P
; b" I% t( _: l9 `* Z" Q) q( v
            // Load & render glyph
" P# S2 r" r5 \1 z3 F1 Z
) S( j! I; }& m* H, n, n                  
$ B+ Z1 }& H3 R9 [0 o% e2 S. ]0 F' Q0 _2 W+ C, d7 v
            ftResult = FT_Load_Char( mTTFMsg->face, unicodeMap[dwChar-161], FT_LOAD_RENDER );//读取字体
/ j. c$ _" F! r' G+ F5 _4 s
0 X5 Z' ?+ L3 k; a0 u, l/ h            if (ftResult)
1 ]- r# U- P! k: Q$ y! _8 S' s# v2 J
$ X: E) P3 t  b- u+ J' K. h, @  l& B* P            {
; _# V5 i8 e. X  u1 M. Z* h
3 O8 U- f( I) L5 Q                // problem loading this glyph, continue ( Z# q! M- M$ d# C* O+ R

* q0 y. m. Y* z                LogManager::getSingleton().logMessage("Info: cannot load character " +
1 B% @) i, S' K* x8 V
/ h8 [4 k, Z: U  [( u; f, g                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);
3 M+ @# U; h& W* I
- {$ t) H9 L, r, W                return false;//如果错误跳过 6 G- P9 c+ U( K7 W1 e8 [8 J
1 H7 Z. n: j/ s. f* p" d
            }
2 O5 j! ^3 C0 z) }9 D* Y
# \7 {- P/ E' v  
1 ~3 M) }8 F" ?; j% P" L; `4 Q  a$ K& H, d6 U. O( o. i. W+ D
          unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;7 y  E. x0 N0 S" i7 O

9 \9 W" u3 p! ~0 a5 j                  // 位图指针 1 S$ q& X1 O# X

) g( M6 z" \; P3 `            if (!buffer)/ _; R# n+ L6 n8 H% @1 k
1 ]' f& }2 K/ V5 F% k; n7 c. m3 G) g1 v! T
            {
" b' y" t8 k' J" r9 N$ [8 a
3 }; A' r8 t0 s! J: E; R# T9 `                // Yuck, FT didn't detect this but generated a null pointer! - ^+ _3 a6 W# l  n3 w

( L2 `* L* W  ?' t2 b                LogManager::getSingleton().logMessage("Info: 1111Freetype returned null for character " +# ~; e/ I0 ^, Q8 J( S

$ r) w: q. U; D( S1 G                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);
2 X* M& `* O# N' m
7 m: g9 @. R; X                return false;//如果得不到跳过
& @0 ?, Z* _, s" Y" L4 h9 T) D% i* J( o8 q; i" r* Y$ `; h8 r
            }: x9 ~7 Y9 {' n" A! u6 `

0 I4 g! Q! Z' @/ @2 Z; _  @" Z    i6 {6 p7 Q8 T, J. b3 E

1 w. F3 V  M1 Q) ^* P2 ]% |                         int y_bearnig = ( mTTFMsg->max.bear) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );. B/ Z( D/ d1 Z3 S! y

' r. N2 |( y6 ?$ |4 r( u0 ?      
1 c8 L. D" E' ~+ i
' f5 w, n' i; G" u" K                        
4 Q4 O; m  v7 H/ G- {. n! ?' h- |. \& r$ _
            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )
9 a8 f7 J$ O7 D/ q! A# B: _
% s* u: d  K7 s2 w0 b            {3 a8 n+ z) k6 n% _8 V$ S& ]
) m6 k4 `  ]! }# F" b+ z9 u( L
                int row = j + rect.top+y_bearnig;" u3 `8 B6 [; y% ~* z; O3 O
( h2 S" G5 N2 H% U/ {3 T3 l: ]
                int col = rect.left;//列
# \' V% H; e- R* y5 H
' O9 O& K7 D  v( o  M3 ?; @                                pDest=mTTFMsg->imgchunk.getPtr();4 T% E7 w9 w! P* Q& O  p

$ q5 H: Q+ |' x  M  3 x" q# y/ h4 a5 q) e4 ]
* w. h  c! C# |) M+ B* r+ U4 m* w7 w: B
                        0 f5 U) t3 @) C% H

" B0 H5 P3 L- N+ q# W2 m, I                                pDest+=(row * (512*4)) + col * 4;9 H) G7 `7 I- g* v0 Z
1 W# Q. _' M8 ]1 f& I. m4 c
               for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//每行的点 9 k5 ]7 v% @5 P7 v: z$ x6 z
; w0 E9 {) u; ~$ ~, r* W, j
                {/ \" v- |* g9 v

; f6 ]8 Z% V& _" I. l                    if (mAntialiasColour)
5 b1 V% M/ p2 Q& f" Z- h4 n3 O9 _. ^/ D# L: ^8 J
                    {* @. U$ R" m0 y8 N% n
: e) L) n  Q& H; H2 C
                        // Use the same greyscale pixel for all components RGBA
9 j& d( ~% d; i) G3 I: j
2 T( q, a! J$ y: h8 X                                                        *pDest++= *buffer;; O6 w3 t0 W- Q) c% F2 J
9 D- H7 y. b$ V5 v
                            *pDest++= *buffer;2 X& v2 x; m+ ^# d9 h6 ^/ Y
$ u$ p) m; J6 {( E. R, w2 [
                            *pDest++= *buffer;
( E* B  z' ]2 M) e. M( h
6 t9 p! `2 `5 b% U4 S* g" I) z                    }
$ ^; @7 ]  b7 e3 s  R; q/ D( a5 \) J8 M
                    else : P; F' D) f% v% g0 b; m' G

' s- J) f0 @8 a9 B                    {6 ]9 e) T' v6 e  U  t

" M2 k( }% Y0 f* K  j                        // Clamp colour to full white or off
8 U  [5 ^. M$ |6 ~( i2 _: f) k6 M
4 m& y2 h* s; l- ~3 J4 x0 l6 h                        if (*buffer > 0)
% D4 ]0 N; @9 z- q; e& a
, G" X1 p8 |  H( j: ?& d2 X% U0 V                        {
$ W, D& B2 I) l/ y( i6 n' d
1 r: Y# T9 h* ~0 d! T$ x% E                            *pDest++= 0xFF;
. d3 w% d. {0 }2 e1 i* H6 L6 f* |7 |& X; Y% N6 M8 a# q0 i1 c
                            *pDest++= 0xFF;( k9 y3 t& f$ g* t1 o/ @- L& i
; O' c/ M1 T) J
                            *pDest++= 0xFF;
$ K1 X* [5 ?' Q9 b2 B# X9 d. Y" T; D
                        }9 \$ b1 X8 Q7 Y' u7 }; w2 @/ @

! d. i$ L/ ~  Y/ G/ l0 X9 D                        else
5 J  a, q. L, B9 j( p7 |) j; R! J2 K6 e: l1 B1 z) W  [
                        {$ z: ^- E) Z( v% M+ a9 W
% s/ x* n5 V  ^. Z
                            *pDest++= 0;
0 m( r) a- V, j( D  N5 U) N, {/ j) W
                            *pDest++= 0;
9 |% ~* o2 d! p" j
' d" C) D2 @9 w# |" e                            *pDest++= 0;
) Q$ u/ \) I0 u. g
/ G$ F% Y; u, S8 t& q8 u! `2 D- t# u  f                        }- }1 N+ @! N6 U( n" L
! y/ y7 C4 z6 n6 @8 A  i
                    }
: V3 k5 d3 r6 a# n
. W# E: Z7 O7 Z; {                    // Always use the greyscale value for alpha - f) f$ J% ^! X8 _
' F$ {. H. U# E9 i( I+ i5 T
                                       
, ~* E% N* B1 @
+ y. ^, |# e- u, V& ^                                //      LogManager::getSingleton().logMessage(StringConverter::toString(*buffer)+"is cool");4 a9 X' M! P4 d" O

4 l! x  v4 ?. `% B5 M5 e                    *pDest++= *buffer++;  W/ q4 [) t4 x/ A/ R% l
* [' w, g7 K5 s2 `" O: O
                }
  Z" q6 X. H1 x" s/ Z9 ~% U5 E, U1 h( v, K
                                
, r( q) ~9 N; |* P4 J- R* h, F/ y0 ]3 ]! u: Q7 q, v4 w% N/ ]
                        }
; }7 p2 A. h" H  J
8 e7 ]) e; }4 K/ q: `8 ?                        // 设置位置 & D. S' N0 d2 n/ M7 G+ ?

: D8 w! Y3 S' b                        this->setGlyphTexCoords( dwChar,
* N2 l3 O& d# X0 m/ V
) R# A4 f# ]8 w+ q7 V1 S* {                                 (Real)rect.left / 512.0f,  // u1: X. @1 N5 r3 O  ?; W

4 {( b# @7 s1 ]- k                                (Real)rect.top / 512.0f,  // v1  ]$ s2 B, l0 H+ }; z
: S) J$ I# {) W4 Q
                                (Real)( rect.left + (mTTFMsg->face->glyph->advance.x >> 6) ) / 512.0f, // u2
1 w: n; t8 m2 J: {0 N  G& S" M- _
9 K" b  Z$ t3 G7 T% F5 \5 i                                (Real)( rect.top + rect.bottom ) / 512.0f // v2
) Y' _' t8 E; s) z! u1 k0 y. z3 O  Z* o9 A
                                        );, k% f/ X$ P3 {$ E
# G  J6 N0 u9 k% A# j6 m
                mTTFMsg->dirty=true;//贴图需要更新
  k0 r6 I1 j" }5 @2 N! C+ c- c; V* M7 g- d$ w- z
                return true;
7 W  [  J; V; W
+ E: I# f, U9 L  d' j, I        }9 r8 D4 ?( f" l
7 Q/ g9 ^! X, |, U. u* s: D1 c
  
, e  K  E5 _: U  L, {3 B7 _4 k, i
(4)
7 l+ d9 j. u6 v
* ?- |8 I6 ?. T9 l        松口气吧,繁重的工作都做完了,就是更新贴图了。 , \( x! `# Z2 z1 o3 a

5 ?3 K0 d# P7 Y3 Y8 M3 h        Font类中~
% Q" V* |$ J* h, b
$ p; O) T, B0 g        inline void write()
& L% _) N# n4 b0 c' S4 C& w# {% F( R: V* j  U' p# x9 F7 u4 \7 o2 O4 @
                {
/ W# f3 e5 Z- p1 r$ W; z) M1 g: p9 S& f1 [/ M- [) b
                        if(mTTFMsg->dirty)) x! d5 s" P3 d0 h3 {

  H' o$ K0 R2 y+ q                        {      
) W! Y; O4 d; T/ o
' Z- V& {3 o4 [# h' `! n5 j- l                                // 重新载入贴图,顺便说一句,类似功能的函数还有 ( @: D' z2 J4 I' j6 _
; N& ~; H' _. [
                                //virtual void  blitToTexture (const Image &src, unsigned uStartX, unsigned uStartY)=0 ( x1 n* }6 O: F# M2 }+ V1 {
# t4 e$ ]) [/ @: _# L
                                //和virtual void  blitImage (const Image &src, const Image::Rect imgRect, const Image::Rect texRect)
1 M3 H( a& R8 s, G! H) T
9 H& C3 v( l/ B; t: w( ]0 D                                //不过blitToTexture()在ogre-win32-v0-14-0之前没有实现,没有尝试使用。 blitImage()就算到现在也没有实现。 # T$ ?8 T+ W2 \' k; ~! ]) S. O
0 j# }' ]4 U* w! T" N7 Q2 |5 O
  
; l2 o; K: v; T5 |7 Z5 {4 K  O# c' o9 d, a
                                TextureManager::getSingleton().unload ( mName + "Texture");; {5 q% x% [/ H8 j  ~

% r# Z; e. b& t                                TextureManager::getSingleton().loadRawData ( mName + "Texture" , mTTFMsg->imgchunk,512, 512,PF_A8R8G8B8, TEX_TYPE_2D, 0  );
9 \( h: h( ^& U( F2 K" z) s7 }- w- W1 ?: F* s3 F
                                mTTFMsg->dirty=false;% `. s/ S7 ~6 I1 z( l0 \+ v8 _

( D! P5 h# }7 A) K1 ]$ J                        }4 }; W: {+ h, m7 ^$ N( A: d
/ k3 R8 v3 k8 _
                }
, f2 n9 b, C: U& O4 t- I. \
5 w3 o0 g% ?. j' }- Y- c# J4 d4 y  
" Z; R1 \  v( C4 H: d; i' k  V! E+ j1 j( z  f
         在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。
9 o; l- P$ Y! B5 o! q
! n* g7 W. m( |! b3 A  2 }) {- b0 \$ a: l* x# G
& P0 }% c4 U6 I6 e- z- }
  
( x8 K6 h8 ~+ v8 Y% Q$ I5 n8 F3 O; I
4.结果。
9 B# v5 Q% s6 M  ?9 K: @) A' O
5 I' n7 C) ^3 o/ K# h# L" {( I        好长阿,写了好长。虽然多是代码,但写注释也很累啊。重温了这些天的工作结果。就像上一篇一样“在OpenGL和DX9.0中成功的支持了中文,但是DX7.0中竟然出现了运行错误,具体问题还不清楚,还望各位高手指教。”。不过本来OGRE就不怎么支持DX7的,不管了吧。OpenGL中渲染的比DX9.0清晰,是我的显卡的原因么?以上的winXp+vs2003.net+艾尔沙980se通过~。。
2 b7 @/ O0 v' S
; n9 O+ ^$ [7 j- I4 ~" L; [" o        顺便说两句,上次发表了拙作,没想到好多朋友和高人们找到了我。甚至联系到了一个南方的公司,说要做一个引擎支持中文的方面。但是卖完400多的火车票之后竟然因为住房问题作废了,5555,退票少了80元啊。还是自己差阿,如果再多学点可能就能要我了把~。努力吧,争取写《让OGRE支持中文》三部曲。 8 B$ L* p7 u8 Q% q$ U) W0 x
& F0 [) Z3 @/ Z5 n' h# ]
        下一篇应该是《可以输入中文了》。
4 |% v) _1 s, I; S9 B
+ `( }, C- k# t        也可能写不出来的~~~~~~~~~~~~~~~~~~~~   
4 z. g& J( |/ b7 p' K8 F7 G, \5 x+ r. E' w4 [3 Q  j' o& o3 w  d
    相关文件
* u4 J- f: v/ D% t% v4 S5 s& [4 y4 e) s: }
    chinese.fontdef//字体信息文件 放在资源文件加中
. m6 O! @6 R1 \/ b1 w' s( f
+ A4 d2 h, I, `1 `& A4 b    font.png//字体图片 放在资源文件加中
  ~0 W2 \- k) M7 S0 X/ x# U$ p6 V. i! S. }: U
  
" O) v# @) G! ]6 X/ M5 M% j, j$ c* t* Q  l/ a3 c8 R
    OgreFont.cpp) V$ s3 i! x$ R( a
1 V) d0 S6 }: D: {9 e
    OgreFont.h" h7 s4 }; ~1 |8 e
- W, x" H# O/ a+ Q9 C9 U0 V/ ^
    OgreFontManager.cpp
4 g/ g" n; j( @4 p: Y! ?& S( d9 T, L# O& U$ o
    OgreTextAreaGuiElement.cpp/ y" }$ a& ^4 A8 K/ h( f0 z
2 I5 V) G! @' }5 R
    //上面文件覆盖同名文件 就可以 先备份
( v7 Q: `/ k  ]. s" H7 a9 s
! T0 ?) n; V2 r8 R# ]   
- _' ]3 E/ c' i* P" A9 a  M
2 D, G7 ]) T8 i   solo5.ttf//这个是一个中文ttf 我直接替换了原来的ttf' N. Q7 f' F) j1 ?  t7 c; }# S
- ]% z9 R( a; G/ r
   unicodemap.h//这个重要,是换算unicode码的数组(文中提到) 3 w# ^4 k0 M* p% X

+ j9 z# f) Z+ _4 i  ! T! F7 {6 e. V6 O: D
4 k/ z5 |1 K& t3 i% v
这个是在ogre-win32-v0-14-0基础上改的(上次是ogre-win32-v0-13-1),
/ v  K. N6 Q+ I4 M% Q  A: A  O3 n* ]6 R. u
请到http://sourceforge.net/projects/ogre/下载 4 y+ {- o( |6 R, a- r4 W' ^
$ a/ a/ ]- l9 u  c  m* b! Z2 f% S
配套档案下载:http://www.gameres.com/Articles/ ... /ttf.files/file.rar
9 i8 ^/ \- t( U$ I  F% J
! s1 j3 n  Y8 ~- }& E$ X 免费打工仔QQ:18500701 ?  |8 ?% \  D; {
" V) f$ k& j- E5 h$ ]- p
From: GameRes 0 o5 i; I: D% x7 ^9 F. [9 k
3 [) L3 n6 t9 r
http://www.gameres.com0 J! F! c" _7 y* |; g

; j% R& p' d% [) R上面图中“免费打工仔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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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