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

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

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

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

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

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

开源的图形渲染引擎OGRE(3) --让OGRE支持中文TTF字体9 Y+ G/ q" m; _2 S; j
& l; @  C7 H% B' n
0.还是前言   {  ^# `4 l. C. D) H) u

2 G% y9 S2 j% n/ k9 k  G        如果你希望能看懂这篇文章,请先确定你已经看到了《让OGRE支持中文》(http://www.gameres.com/Articles/Program/Visual/3D/OgreSupChn.htm),因为本文是在上一篇文章的基础上写的,并且假设文件都已经按照上一篇文章进行了手术。但是如果你只想简单的使用TTF字体,只要下载本文附带的文件,重新编译就可以了。 7 v; ~* {2 |# l% t

% ?8 w# Q$ f7 L' U% Z, S% c" @! E# F1.检讨
) t3 Z7 d; E# m, d6 h7 X5 E. e2 p8 h! U+ k! z
        正如上回说的,我们已经实现了一个位图的字体。但是当冷静下来思考时,就能发现这种方法的诸多缺陷。读入一个2048*2048的位图,等于在显存中保存一个2048*2048的贴图,不说是否所有显卡都支持这么大的贴图,单是每个Font字体类吃显存的胃口,就足以令人心惊肉跳。如果定义足够多的字体类,我想你的游戏的配置要求,在某些方面足以超过《DOOM3》了。 & s, f4 C8 K- H9 ^
/ f) `. w: l6 D+ s0 j! q% r6 S
        而且这并不是唯一的缺陷,文字大小相对于位图大小比例相差太大,导致浮点数的文字位置误差很大,你可以在一个文字旁边看到其他文字的影子。(虽然可以通过增加文字间距来解决。)还有点阵字体本身的缺陷,就是字形单一,不适合放大缩小,一些文字边缘的马赛克,足以熄灭任何玩家的投入感。
& o- N/ n5 d4 L8 ^1 e/ o& E
. Y2 D) Q: q. C# a' D6 C/ q        似乎TTF是唯一的解决之道。   F7 R( n6 L& d4 _
2 Z, [8 H) d" v6 f
2.基本知识
& t9 H7 r' W- B4 Q5 H! ^  u' V) u4 Q. h. Q% c8 a
(1)TTF字体。
& _/ q$ P% i- |- s0 }
' |' {# o: k$ L* D        TTF是一种矢量字库。我们经常可以听到矢量这个词,像是FLASH中的矢量图形,在100*100分辨率下制作的flash,就算它放大为全屏,显示出的画面也不会出现马赛克。所谓矢量,其实说白了就是用点和线来描述图形,这样,在图形需要放大的时候,只要把所有这个图形的点和线放大相应的倍数就可以了。而且,在网站上有很多的TTF字库可以下载,或者你可以去买一些专门的字库光盘。然后在你发行你精心制作的游戏时,可以顺便捎上这些后缀为.ttf的文件就行了。包括Quake这样的惊世之作,也都是用的TTF字库。
. G& C5 s. M- B8 e9 W3 V
: A- {2 q4 `% Z& T6 H(2)FreeType2库 # _7 V2 Q, Y9 U# ]2 ~. ?& O+ V
4 _8 a- ~0 c: r$ q, e
        在http://www.freetype.org,有一个FreeType的免费库,而且是OpenSource的。它目前有2个版本:1.0和2.0。其区别在于,1.0只能读取TTF格式的,而2.0支持更多的文件格式,在使用它之前请详细阅读所要遵循的Licence,以下是摘自FreeType2.0对字库的支持列表:
- z8 t, u9 q. m! [- T0 f. r- k# I+ r
        TrueType fonts (and collections) ' o+ s$ T. P2 t$ c

' @9 f& {9 I. y" N        Type 1 fonts
3 O+ h4 O0 R& N- F$ {# V: b( k0 T% o4 q
        CID-keyed Type 1 fonts ! x( s: T! v" n! H4 L
  k$ R) x$ G& ^
        CFF fonts 1 ]+ O$ v& W- K4 [, Q

9 S( r/ C! |$ n2 v8 U' I* u        OpenType fonts (both TrueType and CFF variants) 2 y7 C' e" m) w

8 {" o2 K3 k4 d8 \8 ~4 q. |        SFNT-based bitmap fonts
# \7 f/ G' o3 q4 A* @0 P
! ~" q; x' x+ A        X11 PCF fonts 6 c5 y* L" Z. \, O& x

) r7 ]" o& I" Y- U. v$ K# T- _        Windows FNT fonts
2 s* @9 s/ G" ?8 f' E/ g0 w* `7 g0 Y) |& |! N  L
(3)“主体思想”   a& K  U$ c% @. {. O
) }) I. n1 c' o: _
        请参照炎龙工作室的《游戏中汉字显示的实现与技巧》这篇文章,可惜使用的是Windows API,作者千里马肝,上网上搜一下吧。 1 ^* R$ i7 Q+ \) D
4 I) a( b3 [- }, B
        附带说一句,上面两条都是直接从这文章中剪切下来的,>_<  不要骂我啊,不知道算不算侵权呢。
( W9 s2 r' b% `% D% r3 G. Q& e( j  q0 n- [
3.动手术---比你想象的要麻烦 9 e, T8 b  r" ~, d5 }, B
(1) - u9 y' {* O: n
        首先要告诉字体类,我们下一次渲染需要哪些字。以便字体类可以在需要的时候释放不使用的字体。 ; Q  F  a& A$ J8 e6 d

$ A/ p4 J2 R5 p( C. U+ R, e        在Font类中~ " {* N9 T  \0 f7 K
  D7 @+ j" [* P9 {
        a.增加数据 bool mUsing[OGRE_NUM_GLYPHS]; 用来标记文字是否使用。 ' b+ d- w- M5 ?$ b  m

; U, |0 y) \8 L& A3 [0 p        b.增加函数
0 c8 ]$ I  t& y* L1 d' e! c$ ]" w  x% ^+ R6 _
                inline void setUsing(std::vector<unsigned long>& caption)& a9 t5 |- A. @6 g' C
, a& @% D: b) L0 |6 D3 E# S
                {0 u, F9 L* C. @2 n: e! f
1 t' m, q! N1 y5 c
                        memset(this->mUsing,0,sizeof(this->mUsing));, v% m" s, K7 S* ], J8 O8 R3 R* q
  n9 E3 W- S' ^5 C. m' j/ c$ |' ?$ n
                        std::vector<unsigned long>::iterator it;
/ `1 k( X8 N! a* |0 T. h7 |$ K
' d6 ^' q3 \# H) c" F9 H' V, m                        for(it=caption.begin();it!=caption.end();++it)
# H# h/ w) G8 A( K1 R( u  x6 @; k5 X- `$ T! S. f0 h
                        {' W* w. n4 G! q+ D3 K6 F5 _
# _) s! H1 p4 M) _% q
                                if(OGRE_GLYPH_INDEX(*it)<OGRE_NUM_GLYPHS)  L. }: Z" {, Q) W& {
' }) B; J& ]  ~$ R1 C9 ^, a
                                this->mUsing[OGRE_GLYPH_INDEX(*it)]=1;//标记文字为使用 2 C# v" N9 O5 c. a
$ N7 p, P( G, \4 a) O# E
                        }
. W' v% a9 i, y) L5 u$ N+ X' @4 a7 z$ B1 f3 r& w' c. j
                }7 Y& c/ {+ r, f4 F/ s
( S! M) S7 J9 R$ b7 J8 K2 U, J) r
        并在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。 3 Q% q! y7 f* W4 E8 S
(2) ! Q- K- Z! H$ @0 A

" d+ x& y1 f! |% ^0 t        然后是修改void Font::createTextureFromFont(void);
7 Q. r4 ^, s6 j! |  Y: A9 {" @% r  R5 w" I6 i
        Font类是通过void Font::createTextureFromFont(void)来把通过FreeType2分析好的英文字画在一个2^n*2^n的贴图上,然后再保存英文字的位置。
+ ^4 D/ K6 @/ }7 {
) r" L  C$ |# b( C; O        我们需要修改的是:
4 ]3 [: o9 I2 d4 G9 a+ E0 t. d7 k
' ^- A8 R( u" {$ }! m        a.从函数中分离并保存画字的FreeType2和辅助变量。我们通过一个类来保存和处理这些变量。 # E$ B0 z/ [6 R- k% Z

, N" I7 C' X) `        class TTFMsg
. J3 ~  w  w1 D6 }# M1 ~6 Z$ m# `9 t. g0 H4 Q# p
                {3 b* v  ^9 D0 Y# R) }+ Z- d
. @% a# Z0 G8 S8 _+ _! q
                        class Max//类中类,用来保存几个"最大",
) |. t/ c: ]  P
' A0 j- w; A5 n5 `- u! M                        {+ j# G: U" p7 ]; k
5 W7 G6 m) N5 Y, @
                                int nothing;//这个是用来占位的,没意义,反正没他就运行出错,可能和数据对齐有关吧。
5 U8 g- l% y7 E$ Z" L: \0 c/ b1 C
                        public:
4 h8 q8 D* e! ?; k+ s* J                                int height;//文字最大高度
3 c8 z% k( m# n/ p" Z                                int width;//最大宽度 5 o- l, O) v: R' [( p3 x, z
                                int bear;//最大空隙?
8 u1 D$ n2 T9 Y! L4 O                        };3 q4 h2 \1 P4 H1 N" i- D+ o
                public:: u# h) \( a2 I$ A* s
                        FT_Library ftLibrary;//FreeType2用
, _# R9 M: u8 n+ b$ v                        FT_Face face;//FreeType2接口? / N: m$ k3 N" F% s( l
                        uint char_spacer;//文字空隙
" G- Z6 _* {9 w' \- }                        SDDataChunk ttfchunk;//数据块,用来保存ttf信息
0 [% I+ w+ ]8 P0 Y                        FT_F26Dot6 ftSize;//FreeType2字体大小 : d2 [1 N. p. R- l6 C/ {4 a
                        std::pair<uint,uint> point;//在位图上画字的点
# r: h+ [) N: b) ]# h0 R- n                        SDDataChunk imgchunk;//数据块,用来保存位图信息
( j& ]& }3 W# J( O: w+ z                        bool dirty;//标记,看是否需要更新贴图
5 l- R7 s& q6 |8 _+ y                        Max max;//几个最大 % V5 d6 _! L" F! S8 I
& ^9 P" w2 ]1 L  A+ |
                        inline bool init(Font*  font) //这个是初始化函数在void Font::createTextureFromFont(void);中调用.
0 b5 c, u) a( u- G2 K5 E) Y7 F1 h2 L7 e, A" S
                        {       , r7 {+ f7 \% M8 q- |& K6 l
5 E3 K5 [+ M7 p/ m3 L7 O
                                //以下都是初始化,大部分都是从void Font::createTextureFromFont(void);移植过来的 % n9 O# ], l; d: N3 W" I" p4 Q8 ?
. @" W: n6 E+ q( q! _7 x
                                dirty=false;
% R# F4 W2 X' i4 S: n
  W- h) n: G; l                                if( FT_Init_FreeType( &ftLibrary ) )" c& D) U: W+ }+ D- Y
; R! y4 o; i* b3 J: A# f
                                  Except( Exception::ERR_INTERNAL_ERROR, "Could not init FreeType library!",
1 V0 @" n4 O6 t' y
1 ^8 e. w9 u6 e- S                                "Font::Font");  w% G  D. Z3 G7 g
$ _4 e9 V8 o/ @4 N; A
                2 T- E8 \/ f0 V( h# L4 q
. w5 D" \  Q, e, E
                                char_spacer= 5;+ s5 O# M# Z+ B' T# L/ L) d" k: i: P, e

. n& s; m1 `9 x2 }* E* f                                FontManager::getSingleton()._findResourceData(font->mSource,ttfchunk);
' M/ E% N5 q3 {" C# V( x
8 P- j' E. n9 w3 d$ n' W                                if( FT_New_Memory_Face( ftLibrary, ttfchunk.getPtr(), (FT_Long)ttfchunk.getSize() , 0, &face ) )
8 A7 m; h1 D) Q3 D- U
2 h7 B5 g" ]3 g9 n% J" s                                         Except( Exception::ERR_INTERNAL_ERROR,
7 |1 T; Y+ v0 I& [& z# [* y, @2 {, r* W3 l2 y
                                        "Could not open font face!", "Font::createTextureFromFont" );6 F/ p) ?9 J5 I1 i" v- S. P
' v& D$ i& n# @: }$ f
                                ftSize = (FT_F26Dot6)(font->mTtfSize * (1 << 6));
& U" y. |3 g/ M( _4 i( Z7 [9 a
1 h6 I  P' z& u+ H                                if( FT_Set_Char_Size( face, ftSize, 0, font->mTtfResolution, 0 ) )
1 P- `0 T* P1 o. @9 |' @+ w& P" o2 C) v5 [5 C* E
                                        Except( Exception::ERR_INTERNAL_ERROR,
+ U. e" s9 y  w) _' _0 a
4 p. Q1 G2 w0 O) Y                                        "Could not set char size!", "Font::createTextureFromFont" );
+ N$ j0 N% n8 }' G; `5 b! R+ f- J3 x* t3 z1 t+ l
  * @- j$ c# _0 f
/ N7 o' t/ h1 J$ N2 C& y+ {
                                return true;; v4 J5 r6 R5 }; y) U" J7 D
* v2 \0 b% [: R+ }
                        }
1 ]' ~4 J8 q& g. B3 u& A
* v6 p6 n: z# _$ W                        inline bool done()
* U# Q0 ?1 A) ?5 Y& K5 [
- d$ y" G% z" l- `2 I                        {/ x: Z+ ^, _4 I$ @& }7 F

- i' V1 F" Y( X8 b$ Y7 P" @3 [                                //在Font的解构函数中调用的,本来应该调用下面两个函数,但是不知道为什么一调用就出错,不用倒没事。
% }+ x7 h2 n! C6 m5 X7 ~' n# R( a& R% D8 c8 O; B
                                //FT_Done_Face(face);
* a, s3 R( r' j6 Y+ K; D+ M# Y) K
                                //FT_Done_FreeType(ftLibrary);
0 _" l1 u: G( K' c" i9 w
; f% r# m2 w2 J0 E2 P# p! {. |2 a                                return true;
2 l- F+ C. n6 l- r  S
9 O. t( L( G0 S) ^  P0 t% w' ?4 w                        }1 G7 H% i* U' U) o! A/ x9 p. I1 K

. f" s; \# K. h- ^8 P& _, K                        inline bool getRect(Image::Rect & rect)//这个函数以后用的,是用来找到可以画字的贴图的空的位置 7 @. u0 i4 I: d4 `; z

; [5 ?4 l! V# B+ D3 Z* z                        {) O2 }& D5 U' U; S

# [' I) V- d/ N+ [/ S0 ]                                if(511<point.second+max.height+char_spacer)
" N) c8 V+ g! Y+ ~4 `, s
! M# Y, u, J- l, t. a                                {% G# D& @  e1 `0 O3 h/ v- u
' P, H1 P2 R/ U# U* V# M
                                        rect.right=rect.top=rect.left=rect.bottom=-1;; N8 X. _" b# R. l

+ T1 ]6 b- a: a+ S6 z8 b: q3 g                                        return false;
9 H- G( o) w% m, P
2 u% h+ T3 W; ]( W. `9 {0 h* `                                }. ^! c+ r4 M# B& T

6 _2 x7 h, B; n% M! D                                if(511<point.first+max.width+char_spacer)3 ^3 y* l& f% @' p8 w

$ r/ h) l( L) h- J2 f, V* [! H                                {# S: _5 W% @. q, y  q
3 ~( ^: f" O* L7 s6 a; g# H
                                        . P, S% c1 e2 j1 E, f

, i. L; D/ O+ Y8 q  s" X3 i                                        point.second+=max.width+char_spacer;9 {8 ~- d% B% `

" D0 v0 v2 X' F5 ?                                        point.first=0;
; D2 H: y. y% p" a6 @. @+ w7 r! s& n
                                        if(511<point.second+max.height+char_spacer)3 O' o- y) T/ A9 m0 M# ~

) A# i( p2 |2 p5 ~/ A" T( i: Z; j, j                                        {
5 n; a& C3 l3 X3 [/ L
4 r6 g( Q; n) R9 j, ?                                       
! {: N+ b, c+ Q$ [) E" M) e9 q, j; l2 y1 N  f* F
                                                rect.right=rect.top=rect.left=rect.bottom=-1;, O+ {. x9 x" g4 ?+ N

) T: ]' B) F/ n- ~7 b1 h                                                return false;
1 a( c% l3 B5 T- g( @  v& }
/ D& a1 ?, o$ Y, g1 C                                        }
; F4 y! @8 v$ e% \! X* S4 z
7 y6 v. B1 F1 A& S                                }
/ \& R. N' W* q( `% j- O2 B. _5 s
                                rect.left=point.first;& v7 `) _$ q) N/ e3 @( d
, C. X# G' k" ~1 Z& U
                                rect.top=point.second;
- o5 P% \. r$ h( O9 Q" Z. [3 ^% I( s5 m3 g9 E) m. b' i
                                rect.bottom=max.height;
, a% x& X3 \. ?
. a) Y0 T) ?# e# {- ~7 K                                rect.right=max.width;. v% l9 l/ S/ v0 L1 Z+ m
: [3 _0 x9 a% [# B' B1 ]
                                point.first+=max.width+char_spacer;
' N6 ~( K/ R$ N# N& p+ O+ i4 ?9 ]3 P9 }
                                return true;/ B8 v0 F# F# N% P! W% z4 l

# @: T& {: k3 S( M. `# v1 s                        }
7 w( W: n/ V# V0 }5 w0 t2 w8 A1 l
                };+ g+ j: n, j! L  B

: A% M- x$ C5 U4 |# q  n) l        上面的类定义在Font类中,在Font中增加 TTFMsg * mTTFMsg 数据,并在构造函数中 mTTFMsg=new TTFMsg;
7 ~. P% r' g4 @9 W# B
! Q, y3 S% y" w7 d  O2 e/ h1 H" w        9 ]$ k, g$ X8 a1 X. K! D
: v/ i+ R) ?( I  d( |
        正是修改void Font::createTextureFromFont(void);函数,主要几点,首先是分离出很多变量和构造到TTFMsg类中了,然后是贴图从2^n*2^n变成固定的512*512,为什么要这个数字呢,因为256太小(废话了)。能保证512*512大小的文本区不会出现不够画字的情况(所有英文+符号+没有重复的汉字),这个安全区域基本上是够用的。(什么,你要画满屏幕的汉字?哪你自己看着改吧。)还有一个重要功能是,要找100个汉字,找出最高和最宽和最大空隙作参考。修改完成这个样子了~7 d% I" H6 F6 S) t  R. X! W, R

7 Z' I7 x" u' ^. @( ?    void Font::createTextureFromFont(void)0 X! o9 Z; a# N' |

/ V. _4 @6 V/ B7 F    {
; m0 k% |0 c" u2 u2 @( F1 {* Q
6 W! I( |- V) j$ e! y5 `' z        mTTFMsg->init(this);//初始化FreeType2
. c# l3 X1 y2 H" B& z% E
* h( Z% R/ X  N% k        uint i, l, m, n;
3 d& j$ f! b: P. H
; d+ M9 S$ S  a. R" S' Z9 x        int j, k;) `# [3 O- e/ g  K' k2 C& G; S* _

% {. d: ]7 ]: U4 P: j  
; W# N+ X0 r0 O% }0 K# e5 l3 G' y: w* B' t% T6 f) j$ X. i$ s- c
      
' r3 X0 W0 G3 r& D+ B( T( T9 S1 @  q# C
        FILE *fo_def = stdout;//啥意思?我看不明白
& ?  r' x9 O2 S7 @  l8 I. ]! x* u5 h
  . J8 J4 g+ O( J# }. i! b+ D8 \7 ]

, y3 t1 T( F6 A        int max_height = 0, max_width = 0, max_bear = 0;
0 D5 |; n8 i1 `( B# W
# w4 u9 U8 k* m! |  e4 I/ e3 Y  
, j" n0 _. P1 T" H3 ^8 L
; }! `! Q$ b% q0 X+ i' J. T        uint startGlyph = 33;
6 G( g7 H6 V( q, H3 V  @# a; f0 S9 w3 d, l7 o" A# U
        uint endGlyph = 167;
% m' I3 J8 M4 @; ^& a1 d; P9 t
0 k1 j7 ~3 Z" Y6 H4 X; C  1 T5 g9 [* z) A2 N
$ j+ h3 S9 y/ f7 B6 B
        // 找英文的找出最高和最宽和最大空隙
- U4 ~4 S' c# p. [& [+ |4 U
! J0 v6 Q- R" M) O        // Calculate maximum width, height and bearing
% q* U1 `( q; y" e+ D
* C* \+ J2 {6 U        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )4 t. ]0 }4 C4 J  L* t* v1 V
- U+ P) t! m; T* y0 I
        {, c1 L0 a1 `3 b3 l; E$ N6 m

* y2 R9 `4 D. h2 q) G            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );* G$ y  ~, V  W( E5 _+ C
, D# P& O& w/ h6 p# B
            //以后的 <<6和>>6都是FreeType2中的数据和我们使用的数据的转换
  f$ E! q: r  L4 l$ X4 |
0 h9 S2 X( h1 g* z0 w            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height ), I( f6 D% }" Z5 B7 i" E( s

$ T% W) V# f' V/ Y( y+ @$ K                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );+ O8 i, ~! \( y
  ^$ s# y& _& h+ r6 ?  U& x# b
            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )1 s5 F: j+ z, v: R* f

& U, M, r+ o* q2 g                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;6 }* x8 V+ W. U) g
: c+ G5 x1 S6 F0 H6 s
  3 z* S$ Z; S. q9 z; S
# g4 h( }' w: O- O8 W
            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)4 H0 j4 e) v3 w7 M/ H

: X2 s" G8 |* K9 E1 L) ]                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
, L1 p& N5 d( l2 Z! }
/ L1 ~0 J4 h2 J# J$ S        }, B. m) k& [8 o" F

( m% `1 c, s) y2 Q1 o  ( c  n1 L" P+ D* b3 y1 \
3 S4 ]* L$ e4 ?; [. y7 Y
  $ s: A. q1 K- L2 r

5 ^7 c+ L  {, i        //下面的for是找100个汉字,找出最高和最宽和最大空隙作参考。姑且认为最的汉字就在这一百个里了。
* q/ Y# N& T" [$ n- W
) s  b- q3 g2 b5 {) h- L        for( i = 20643, l = 0, m = 0, n = 0; i < 20743; i++ ). o# d/ K0 p/ C3 o; e( f) @
8 X7 w: t# [: ]2 |# P
        {( o$ e' \' m# w1 d

/ J2 O* ^2 w. m7 |            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );% b) @" O" A0 Z1 R5 G* g! q$ r

# V3 A& Q% m5 I9 p, x; ~0 b  - ?8 |, L3 L2 V
; x# p: h9 K  I7 q! V% r  o
            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )
  z7 T3 p. o( {) R0 S* u4 @: h
; t, c1 Y" e# c3 l# j5 l& ~                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );
8 k* r: V3 {" f' R: G# e+ W, e9 f
/ ^8 R% n9 ]; k0 n- ?" a7 ]4 o            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear ). R, o- K; S, ?0 M* T& C& |  H, F7 t
, F4 W. c4 T4 J( P0 w: Z+ g
                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;! G  {- ~' N. {
  Z- y4 D+ I0 g6 a+ Q
  ; ~# h, d( W- l# K* {3 `6 \
* k, }; H9 |% r$ {8 F, q
            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)& c! }7 v5 p) i! g6 R: C
" ]& j; G6 o' b
                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
9 x+ B6 y4 `) n, Z6 W8 X. D( r2 F5 j4 F) p) @% `' w
  0 Q) r/ N0 C. p3 w: T$ j+ H+ p' q

4 P% {, C: q4 M+ ]  f/ ?& |                        
4 t0 M4 }; w! P
& I/ L+ [; Y7 z            if( (mTTFMsg->face->glyph->advance.x ) + ( mTTFMsg->face->glyph->metrics.horiBearingX ) > mTTFMsg->max.width)8 d4 Z$ F6 ?  k* k) ]
, S) ]! E7 P0 F6 X
                mTTFMsg->max.width = (mTTFMsg->face->glyph->advance.x  ) + ( mTTFMsg->face->glyph->metrics.horiBearingX );0 a8 G3 O* P* o5 [  w3 Y* Z' V) p

9 ~5 j- M! ?3 u2 j( {6 V' t% m        }
' T5 F( g$ R. k6 \7 l9 G( l' X% j7 p: C2 k5 ^+ ?- Q
  
2 M% W. V5 }( u& r9 T( E, M1 a9 b* Z5 `! B* H% B6 |3 n
                //下面几行行不需要了 我们要512*512
6 T) G6 g& I# J( U5 ?
3 |" q3 N& R2 w8 F4 J1 W                size_t tex_side=512;//就是这个了 512$ f2 u/ N# ~" ]2 X) m* o

% R+ i5 w  q, d" t$ ~# a        //定义数据宽度 因为是32位的位图 四个char为一个像素,为什么要位这么大呢,难道不能用8位的么,我尝试着改来着,不过改了之后就不透明了。望高手看看能不能改。 / D7 s5 R# [. ]9 O" }' E% {
9 {3 U6 l( o  _4 e4 k0 c( P) t
                size_t data_width = tex_side * 4;
8 h! l. p/ C+ [! O! ]0 _. b+ L0 x# T2 s. J3 |$ D3 f
  
+ N8 z) x" e" s! K1 x$ ^1 {+ Y/ c5 g) S0 r5 \) U
                LogManager::getSingleton().logMessage("Font " + mName + "using texture size " +
% Q+ [( h" `4 q1 Q6 E$ @& j) A9 ^( X# L
                        StringConverter::toString(tex_side) + "x" + StringConverter::toString(tex_side));
8 Z8 E7 L3 L+ X5 N# M2 c6 d" I
; u% l0 `' v7 t  9 Y7 q% n% X# J: R4 R" ^/ B# p

7 r, N% s2 q0 ^: {$ \        uchar* imageData = new uchar[tex_side * tex_side * 4];//设置一个空间用来保存位图 0 _$ S2 E, v4 s7 v7 Z" Z: |
, Q2 o) w- }. M
                // Reset content
* Y3 C3 Q) {* C; y$ Y
$ f1 o5 X5 K! J4 p, d                memset(imageData, 0, tex_side * tex_side * 4);//清零
5 I( Y% v) W% o# @8 `/ _; Z0 o& l6 Z
3 E/ J+ F( P3 }" y  g1 l- \! l  
8 t/ `& H  \% t* `+ g& ?
$ E2 ]* v" |4 q& _        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )//遍历每个字, 2 O2 |3 P  e9 P3 M0 `* K) w
/ X, `; U8 @$ S8 W3 l# {
        {( V/ g  n9 K8 H, j" R

6 ?  F; D* \* o3 K6 s4 Q                        ' h6 t0 ?; }+ P' d* o3 Y* u
  N1 G4 V4 j0 o9 ?
            FT_Error ftResult;
  y2 E* F* T+ P9 y' X- O
: Z/ j, ?/ A0 D/ e7 o  o  
! |0 l# P, `  K4 R0 W2 [
# |8 F( F: r/ B4 M9 c9 m! e            // Load & render glyph ' \8 K; v8 }3 z; H' r; T, P3 R

. I' Z6 h# R' Z8 o6 B- u6 b            ftResult = FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );//读取字体
7 @( t( p, C  ?. @
+ R2 P; R/ J* G% X! g5 L            if (ftResult)
. b) G( p; B  a  v  \6 d
' ], \0 Q) _& u0 e8 n3 I$ L' a. m. p            {( D( a% V( g0 _( m

5 z3 J: F! ]9 E8 y+ v* X! B' R8 Y                // problem loading this glyph, continue
. C/ k% j- Y5 A9 j$ R/ o2 ~9 A* P; j) Q3 y
                LogManager::getSingleton().logMessage("Info: cannot load character " +* R( \' d" Z  s& R% l$ _2 x4 t
0 U( O  s& Y& i4 Q8 Q3 r0 u
                    StringConverter::toString(i) + " in font " + mName);
4 Z* y/ c4 m( z. L% h' k4 L, c. O5 h: k  `
                continue;//如果错误跳过
+ g: ]. U' g  E. s/ ^1 d: h& G% m2 ~- u- D
            }3 L( V. G  f/ ?, L
* E! k& v6 ~3 B- A0 ]9 c
  
, E5 H) D( f) b
& }. R. _& b2 B+ C                        // 应该是字宽
/ G+ d* g6 T7 w
. }9 ]8 `) j1 ?  l7 I2 U                        FT_Int advance = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );# ~  o( h! {, J, A5 z8 U, ?
- X4 o: q8 Y- ?4 k. y, a* M
                        
. Y; {2 r; k2 @0 P/ f0 Y1 ?  o
; Z/ \8 l' U& b6 t8 X  P& E3 Y                        // 得到FreeType2的位图
3 e9 h4 w; S2 S& a& X
: l# \' D7 p+ i: ^( \5 |            unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;
  Z8 |9 c: }/ U5 T2 k4 n5 c+ r) V9 O
  % q$ J( s6 P) E3 i$ B0 w

* ~# b$ P+ r  h! K            if (!buffer)
6 [9 b" B6 E  o! @  D0 ]6 l0 {+ ^; h/ ?+ N
            {
2 v1 s" X  x: e3 J9 [& [
. }5 V- l0 `' Q  g  \9 o                // Yuck, FT didn't detect this but generated a null pointer!
0 b4 Z) j9 |7 N& t# }
' S/ x0 A# S4 P: A                LogManager::getSingleton().logMessage("Info: Freetype returned null for character " +
) R  W2 N; N0 W9 F& R
; n& J6 J8 X) @                    StringConverter::toString(i) + " in font " + mName);) N8 O$ w/ B9 E

4 j  X3 e2 X! u1 v( N' ^                continue;//如果得不到跳过
6 }; ]4 g$ s1 k6 L) }" w. N' a+ b5 |: |( ~+ d/ Y
            }; C3 }) W2 I7 e

' c9 P4 [# a9 s1 {- V, T7 h  
" \& j6 B& u; @, s5 ^$ u
4 j; C6 I, D$ j6 Z# _8 e0 U                        // 得到y的空隙 (最大空-空-本字空)就是说空出这些字底部就平了
8 u- Z. v- D9 }9 b. n6 a7 t0 b) }" w& w. M; t5 X/ i% ?
            int y_bearnig = ( max_bear >> 6 ) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );
! ~8 o8 L7 M0 t3 |: A# W' t3 V0 r, |2 t5 J0 y! m' o
                        
0 H# d3 V: l$ j6 C; Q5 y; f" E  e+ Z9 @8 W# }) e
            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )8 p, u: K0 Z3 [* g2 s+ w6 K1 n- @. u

6 h$ k, \, _' Y            {
6 q! G- N" A( {4 e
  x; j$ t& h& @  V7 v) \: ]                                int row = j + m + y_bearnig;//相对行+本字在位图的总行+空隙
+ f/ A/ e/ F, d' f- A
* x! S, Y8 e# ]9 _6 U                int col = l;//列
, Y% ]. H$ y5 R# h" ^5 ?: i/ l- }- N3 E
                uchar* pDest = &imageData[(row * data_width) + l * 4];//找起点   ' i+ q4 w3 S+ h

- ]1 _- V; e9 L& R" I                for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//画图   P2 q+ @$ d& h8 {( u$ a. o) ^
8 p. u  P# c1 X; Y( B, v, W7 B7 O
                {" W. ?4 |# T. z, _8 |/ O
" f; ^3 i2 x. y7 I
                    if (mAntialiasColour)//看不大懂,难道是灰色字体? 7 `! J4 F, P4 g1 Q$ G, E
' B1 s8 [6 H- s- x: g* _. C0 k
                    {1 ]; d1 a7 B4 m" }, B' `% C+ D
. M9 \  g" ^' n1 ~* X: T2 L' Q  H
                        // Use the same greyscale pixel for all components RGBA " c5 k8 M# A% j

) _7 @# P- W1 e. K( E+ B                        *pDest++= *buffer;3 l1 @  A6 U5 y* I

% L# Q  x8 K4 v& C                            *pDest++= *buffer;
1 L; t0 ]8 b2 r$ @% K3 v7 f9 b% c
( [6 x" T5 o' e5 M$ N1 M                            *pDest++= *buffer;% b, ^& q: L& p

, p- A+ \$ }0 J/ Y! I9 ]                    }- P2 V8 `$ {3 c8 B5 \7 b
  b5 ^4 o6 r- r* P% _  \$ y! ^
                    else / \6 R7 U% a) v

& q" q& S% ^1 E! V                    {4 Z1 v( b5 J9 |8 ~
' Q. U3 T3 Q0 d' M, s# S
                        // Clamp colour to full white or off
- W- T  B0 B3 z, {- W
. N8 r8 u' ]9 ^  {4 b& c                        if (*buffer > 0)
/ I: W! g8 S$ J1 U- W8 O% ?( D) r3 H) N5 f
                        {
; Z; @2 Z( v; J- Y& P! g4 B" C
                            *pDest++= 0xFF;( X0 }* t) U3 C) ]

* @  \7 `1 O* D5 z                            *pDest++= 0xFF;
$ e9 E3 _& u, L# b1 \1 z2 v0 U9 F, O) [% |4 ~
                            *pDest++= 0xFF;: ^9 M. f; W/ X; z% |

8 X# V6 A( G# t8 O' Q' l                        }
) Y; H1 H9 b8 u% S2 j4 G
6 p' V, d9 J/ \8 c4 N                        else
# I' o6 t0 b, m$ h
# t! z8 E3 i: `. L                        {
3 |  F$ n0 M% ?) s! b, v8 \! F# _7 j$ V6 E
                            *pDest++= 0;; l3 }: K2 M, P" Y$ i
6 ]5 w# C  s, ?# b# V9 [: ]
                            *pDest++= 0;
. {: {* ]; A: U$ [8 g" @, `' T3 k- E. v+ _
                            *pDest++= 0;
4 @* a; ^4 H& l( p" ]; T4 l. a, q
                        }
& F! Y! S6 ^/ J6 n2 h
* O8 P/ P/ W* {' J$ a! @                    }- R% ], B6 E  R! Z) D
+ F6 C& d- _9 q" b- R3 P
                    // Always use the greyscale value for alpha 7 W. D2 v. G. c9 W/ U

0 l  i; A& a- R0 G6 u                                        ' U  b4 X4 z4 e; K- V% ]( O1 d

- R9 L& o  l$ {1 e" @5 ~; V                    *pDest++= *buffer++;//alpha! 我是一点不了解了为什么是这个? $ q" \, _5 S( P9 L" f7 e6 D* L
. u! K) r4 l& D$ s4 u, ~/ l
                }
% n' Y" c+ T! P1 Z+ H
1 s# Y- N9 U6 I; q9 p6 v+ |            }1 e& s  S4 O+ @8 u

% m" t! Z  r& _7 A# E: J  7 `# K* N3 @: i9 P! `+ ~) i

5 T3 A# Q* s' f3 a1 F1 E            this->setGlyphTexCoords( i, ) s) \% u( F$ f

, z* x* Y% X* Z                (Real)l / (Real)tex_side,  // u1* G+ s1 T1 q: C+ Q0 I3 ?

% Z' z5 K' p( m; ]                (Real)m / (Real)tex_side,  // v1
" z4 |3 ~1 u* R( m* j: i
* H% K0 k& q% \9 u' E2 N( }9 ]                (Real)( l + ( mTTFMsg->face->glyph->advance.x >> 6 ) ) / (Real)tex_side, // u2) y; N9 R  [; n
) N/ u% Z+ t' K, e2 x+ |( J" e
                (Real)( m + ( max_height >> 6 ) ) / (Real)tex_side // v2
+ P( G% A, P2 ~7 z" w) W: j5 s9 O4 U
                );//设置坐标
: p3 G, x7 u0 @* g0 Q6 l6 x. ]8 v
' M1 {# R  ~# ]9 T! p$ a( C+ V" a  
0 l5 {6 V9 ~7 w
6 _" c1 f' `0 m9 R' e3 G            // Advance a column - d. k8 M9 ~0 C/ R+ \) V

0 Z, [1 ?$ p2 I9 Z            l += (advance + mTTFMsg->char_spacer);8 G% P% y9 Z( X2 s  D, f$ G* E$ s
) Q1 h  k) {  H. G& ~/ S2 q
                        //l+= 本字宽+字空
! E& v% U: y& K3 ]2 F( z# t" ]: d& r; f2 M! _) @
  ! E1 j& l: W0 F5 s
& W, M; W. q4 Y) a* j7 h# c
            // If at end of row
  p8 _. i" e: R. R( g; M
5 [- g1 |) Y8 q7 Q3 Z, o                        //如果到头容不下一个字
9 u6 C2 s/ `- D$ M. U" |7 h) N
* r9 A& I* J& K; R" S7 B            if( tex_side - 1 < l + ( advance ) )* m7 ~2 w% F- a" i5 N. P0 F

: R, `0 j* z4 R; t! x0 P            {4 l: E% |  @& y# [6 A

, F+ E7 H- Q9 y( A, t# M5 v                m += ( max_height >> 6 ) + mTTFMsg->char_spacer;
/ v5 t+ c* w, _' ]: i) V2 W3 k- P5 P( F
1 J" y: A0 r- x/ k                l = n = 0;
/ M; ~0 A5 f' {; D5 w
) s8 Z2 v' i. n            }( g6 A5 C0 e3 f' l
% N2 t- l3 c# |% j: L% j$ ?
  9 d% u$ h7 h7 y# a* Y- f

# x  q, v+ ~, c3 s        }
! [6 n4 _. M; |0 Z7 B0 V. H+ s3 e
                // 把信息存到我们的mTTFMsg中 >_<
: Q( p# a& @  r: ]# a+ g; x2 I8 ^3 W( J" Z9 J# l7 u, P
                if(l)4 v2 W+ I/ X; c( G

2 \$ }7 h$ _+ ^  h; D1 ]5 _1 G                        mTTFMsg->point.second = m + ( max_height >> 6 ) + mTTFMsg->char_spacer;  m% {1 a2 p! [4 g3 X  y' k' [. ~8 a

! M* v* g9 I: ]! l* l% T6 z! A                else " _0 A* x3 w$ D

+ g3 @  |8 D* y8 @                        mTTFMsg->point.second = m;" w+ {' Q" ], V) @1 E( d& l

( n! n# O3 b& d2 I0 B5 J; F  . Y4 _; ^* I6 U3 }+ x

9 f" R4 A& o& s- U, U$ {2 ^# w  o8 E                mTTFMsg->point.first = 0;//另起一行
/ J+ P, E6 [* o* C% c1 X6 ~8 T5 `
  + P: q0 {* F4 e1 E1 h! o' `  Q

  v+ a1 S( J2 `% [                //下面是保存几个最大。
- m/ y3 d8 Q" l7 a$ m- B: Y! v# U: m* `4 u, h+ _
                mTTFMsg->max.height = max_height >> 6;
: ]- K( e4 q) j2 _# ~. I
) U. l' {# P; f: p, h                mTTFMsg->max.bear=max_bear >> 6;- O1 [+ P: O* |; r- O
' F+ ]0 S0 b# r1 P" M  L
                mTTFMsg->max.width=max_width;7 I: _- A8 p  D; Q* V
' P* S/ r4 J4 z
  3 U# c7 ]% f* e$ C2 b1 O
5 j  U4 o$ H# S# h1 X3 R3 D% m: d  B& }
                mTTFMsg->imgchunk.allocate( tex_side * tex_side * 4,imageData);4 X4 q9 g, i/ h7 N' G" s/ U: K$ o1 D

- E$ {" f( Z6 U7 t0 n; o                ; T5 v' v: X3 i! r$ g2 `6 x
  b2 W1 F, ~. a, Q# F  P
                //不知道为什么要设置img这个中间变量,似乎可以直接从chunk创建贴图 # o3 n! q+ Z% _& @
& h: t: g, L$ }( @" i" E
        //--Image img;
4 M7 f* P' K7 s+ b7 \2 H, ^
  i1 u4 F5 f4 L; w7 b                //img.loadRawData( imgchunk, tex_side, tex_side, PF_A8R8G8B8 );
2 y# K& K1 D% S$ g: s% }) |& \; t& H* H. C
  1 U% Q  |8 J  x4 g% N

; \1 }% Z4 p0 X5 w) ^2 [7 O; c6 T                //贴图名 $ X; E; Z; S# _7 z0 A, t/ j. s9 X

$ U5 y& ^5 n$ n7 U7 O        String texName = mName + "Texture";
( k' J9 y* C+ g/ B* q3 j
7 V! F, S( S- e+ q: U* R/ \                // Load texture with no mipmaps
3 d# b8 x" ?* E/ ^
$ @5 F2 d+ s; E6 r( {3 Y. x3 G        // 把从img创建位图改成直接从chunk创建贴图 ) s' O! ?6 x/ m3 [4 l7 g( p+ ?

) x1 G& h  L# s: f1 a3 P                //TextureManager::getSingleton().loadImage( texName , img, TEX_TYPE_2D, 0  );
7 ~' ^& q* ^8 w# _) w
0 B  r7 }8 ^3 }! c5 w; c1 J: C4 l                TextureManager::getSingleton().loadRawData ( texName , mTTFMsg->imgchunk,tex_side, tex_side,PF_A8R8G8B8, TEX_TYPE_2D, 0  );) h1 I6 L# H# Q0 ^
# j1 i- Y9 y% E& [8 l. F
        TextureUnitState* t = mpMaterial->getTechnique(0)->getPass(0)->createTextureUnitState( texName );. A& j6 t& S$ y  I
( D( W$ [$ O" L$ R# j+ f
                // Allow min/mag filter, but no mip ! l/ v& l5 L: H! K! r4 \. K
# ~8 O# `. {0 B' z
                t->setTextureFiltering(FO_LINEAR, FO_LINEAR, FO_NONE);  m# b+ E* Y& _
/ T# w0 u. U1 H" G, i
        // SDDatachunk will delete imageData 0 M+ r" O$ b! [( c  G8 Z

% b% ?& f% B; M* c' e5 ^        
2 C) m3 X" Y" D1 q- c2 G+ k5 e7 r6 P; p! y+ S: z  J, Q( @; }
    }! H5 k! H! H' D' h) U2 p
7 B  x' q! H4 M9 ^( {* z; d5 e9 t
        你应该对照一下以前的函数,改了很多的。
/ G7 F& r9 T# ]: [
& q6 s  O4 {2 ?2 P( h2 t  
4 t3 B# h' t3 |& U5 q1 [  z8 D/ ]" h
  + l; O) T% \0 o/ @# w% J

% _% p( d9 c& p1 Q& }- l. C3 n. t$ \(3) 0 A+ C& P& w1 E$ f9 E2 S( C

( C4 |: x# L1 X: }! |        然后最重要的是动态的申请和画字。
7 b# G8 Y' K3 Q% I* v# h! l  F9 w+ N( C3 Z$ N& m( n0 Y
        首先最重要的是我们要一个方法得到汉字的unicode码,我们用到了unicodeMap数组,提供了区位码到unicode码的转换工作,等一下提供这个表给你,好不容易从网上找到的阿,可惜这个表没有中文标点的对应,如果希望支持中文标点,就要努力找到unicode码并加进这个表了。这个表是这样的 char c[3]="邸";unicodeMap[94*(c[0]-0xa0-1)+c[1]-0xa0-1];就得到邸的unicode码,不知道为什么没有5165~5169的unicode码,是轮空么?
4 I/ q5 a1 D$ c0 g& t0 z! L* q
) m4 a* h7 _) F. e. H        
0 Q0 }# F. E# t: A3 o8 w2 D" d. v* r( l, s( S$ ~+ `4 o( b, z4 M- s3 p/ b
        申请渲染(字)
8 y  y5 b2 ~, i7 F- `( Q% ~# V5 ~0 O5 E) z
        {
! J( T9 P; }! _9 Z1 O2 j$ i) G" T" f  k# I. C$ I' `
                if(有这个字)
8 u( r; E# Z2 I- c- l0 c$ l4 z0 s5 n( y) ?" C( M
                        返回位置
3 q- c: C# R$ g! V; D- q# u8 f; q8 w' R! @
                else3 }; ?5 P2 I  U6 W- ~) Y" h7 o
! k1 u$ h. F5 u" H& n
                {+ `  d' O3 H) j+ w! Q$ ?+ ]3 D
( p, o$ Z/ c5 y$ Z* c6 r: b
                        if(有空间); a) f- A! ]3 @' |. U
7 u$ x9 U# C) P; H+ |7 ]  H
                                画字 4 ]. n* K- M& y2 a- _  J
  _. x* K8 [# l) S! n1 r, `
                        else: o! @  ?! _6 \9 U0 @7 s6 _9 q

5 m* x) V; B& x- u                            找不用的字//找不到就出错,没地方画了 3 m+ v4 i$ @$ V% U
) w) @# D& q+ o7 i; m2 Y9 }
                                删除 在这个位置上画字 # Z' O/ q9 p- m) i: v$ V4 T" E2 J
! Y9 p# T- q1 f
                返回位置
4 I/ c: F9 B* F# y+ `8 y4 n$ ~& Z
                }5 z7 z+ g& d' y) `8 i

8 D+ Z' J+ f( {5 L, U        }4 ^; R# q  P' L( N4 m1 m; D1 n

% z- @, m7 G0 N/ H8 j/ {! L        上面很直观把,大体就这个意思了,申请渲染的函数是inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )  const。去掉const改一改。得到 0 T) O% y& o  ?
' w2 \- f& o2 f  m1 W) V
        a.申请渲染
! t8 o0 Z$ G( f3 c6 i: `/ I, {
; F( Q$ x4 t) |% D1 l' t        inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )         7 a- ^$ E+ O, i) f1 A& g' n
( D' a7 L7 V% E) `
        {
. i4 w' f# c9 Y2 ]+ J8 @# {) }4 h: b
                unsigned long idx = OGRE_GLYPH_INDEX(id);
1 g8 C# \  U5 t" U# }8 ]4 Y3 o! D
                if(this->mType==FT_TRUETYPE)//ttf?7 }! K3 C: W' U% d/ j* x

1 D! Z) S3 J4 Q' {+ t/ t/ d8 j. }                if(id>=161&&idx<OGRE_NUM_GLYPHS)//汉字?) h  f8 {- y! Z7 _# ~: }# e; U% [

( u) ~- g5 M, z7 z. p, {/ Q                        if(!mTexCoords_v2[ idx ])//没有?2 |7 u2 [2 e1 g% w9 M* Q4 V& O

5 Z/ e  b1 N; s+ d5 g! n' @                                setChar(id);//画字去 + s: d' \. I/ Z& C2 O2 ~
# D1 p& F  V3 m, w# v- a! O0 @
             7 G7 B$ j- p( w0 z, o
! g5 w! V) T( O( O% z" Y! \" w+ N
            u1 = mTexCoords_u1[ idx ];
% I9 I/ O. ]/ D2 S1 U. ?
- d/ S' v  e/ T/ k            v1 = mTexCoords_v1[ idx ];1 k1 ?5 ~$ L- s7 W+ K

7 _: J- ?9 {! k% _            u2 = mTexCoords_u2[ idx ];$ t* `2 \+ b8 T, ^8 s; n+ _: o5 q
7 r# P0 ~* U; L+ s% r+ u/ A& i
            v2 = mTexCoords_v2[ idx ];
+ @* E! @) ]1 `3 s* ^& y5 p
( |! Z% O1 I1 f9 Z( W        }
: h) U; i3 z5 D) ~9 m' z9 E( E, `3 c# Z2 P
        b.画字等 ( b; H, U# G1 A: s5 C

4 j" }  ~3 m" t, Z        bool Font::setChar(unsigned long dwChar)
: \* a# ?# W" L5 K3 C
0 J7 q! D5 ^3 B, a7 b5 x        {
) m/ r2 F% r) w" _5 g
% @  t5 u" N+ |# D' T2 u                int j,k;
; s1 z$ \' F& ]# |% l" N2 s9 W8 u
                uchar* pDest;//操作数据的指针 $ L! @& H- v  W$ K3 R, O* I

( ^& E5 N) x' L                mProportion=0.8;//不知为什么,总觉得中文都太扁平了,所以设置这个参数,在《让OGRE支持中文》中创造的参数 3 d% C5 Y2 L- J3 Y

7 k6 y) l0 B) X6 c5 Y. b                Image::Rect  rect;//画字的位置
( C$ \+ M. |1 V/ {+ R" R
" ~4 p7 Y) a7 l+ [- C% Q+ [                if(!mTTFMsg->getRect(rect)/*回头看看这个函数吧*/)//如果得不到空位置
! ~' M2 C1 \3 l' N# C1 Q: v3 F
: U# a, J1 R! W( A! w                {
& W+ {$ l$ n( |5 f# f/ d4 L: z+ Q
                        for(int i=161;i<OGRE_NUM_GLYPHS;++i)//寻找不用的字 / l/ Q3 J4 x* }0 _! u
. U/ a  C. Y3 y/ ~  v. y
                        {
* {6 B- N4 ]% m5 Y" I. i) h& x
# |) {: X3 L; w  C8 f8 S. K7 x* X                                if(!mUsing&&mTexCoords_v2)
* j- o8 t# I( Q5 ^4 q. p* h2 \) M6 d) p/ s9 p; L9 u* R* h
                                {
* i- ^+ w$ i( e( ?, M+ L4 q  g2 e: h# @7 K# L9 K# S1 h6 s
                                        // 得到坐标
9 H; a! F1 r+ W$ z' ]& D' F* g6 k9 E, l. c! z: X0 d4 @5 Z
                                        rect.left=mTexCoords_u1*512;" [/ y: X, E  ?7 W

4 X+ @' s9 v* K: n                                        rect.top=mTexCoords_v1*512;
5 ], Y; o/ _' O- @4 B2 \/ K6 H! X8 l! |3 J1 o! C
                                        rect.bottom=mTTFMsg->max.height;$ O) V# M+ g( a, h' K. G# K
# r3 x. ?$ K" J
                                        rect.right=mTTFMsg->max.width;: h' c+ b+ m) C/ P8 D0 r) @

3 A; e0 V) Y6 v  `* {7 D  
0 W5 v0 C  [3 K
  _# m- h8 D' c' Y" w1 E" L                                        & e7 I5 {% ]$ l6 W7 \  @! ^% b

. F2 F' B5 f% {/ z% m1 V                                       
% P& k, k! f5 b8 \3 \/ l" E6 t2 |1 h: G2 A& n
                                6 T, `5 s% b. s% f3 A3 o
! v4 R  n. B4 ?' j! {9 _9 f
                                        //擦除(这段代码没有试验过,等做完输入的类在检查吧) & ]$ T5 h  Q; @$ Q, x4 h: x$ g
! P$ E2 E( }5 ]3 b; y
                                        for( j = 0; j < mTTFMsg->max.height; j++ )" e. I6 r( J' }4 [& g  ]5 {+ y

' z1 v- u. o6 G) }                                        {+ m5 S5 m) _- o
9 t( \  q# `/ A5 P3 t' p
                                                pDest=mTTFMsg->imgchunk.getPtr();
* y  z! J$ S7 W6 n# M8 }8 p  O  Y( Z6 w9 p; w: K% b2 w/ x
                                                pDest+=((j + rect.top)* (512*4)) + rect.left * 4;
8 u" }% K& `$ x9 A2 ?/ b$ V: _6 x6 [- q
                                                memset(pDest,0,mTTFMsg->max.width*4);! n. h7 T1 T2 O* x' L$ n* X

1 k; Z* ?, R  e6 g, y                                        }
) _& T2 u3 ]/ f; Y0 d! c! N' X0 o. w+ ]' b1 ?# m: P
                                        mTexCoords_u1=mTexCoords_v1=mTexCoords_u2=mTexCoords_v2=0;
; ]: P# A. l  I/ @# u. C4 C( o: B+ N0 z1 X
  
  J) h4 u4 e. g$ H4 w# c6 D3 e! T. F' p. i* J
                                        break;- t( t- S! l, `: n% U; [
% S% |/ b+ V" k; O# u- R
                                }
8 h5 V* I6 a5 F* Z" p8 G/ y' e  h
3 W$ u/ [9 h7 X/ b, ^4 p( P                        }! D5 w% {: Z* O/ i$ K* U# R
! P5 v4 G3 e2 y4 n7 v
                        
+ \7 \- u# N* t* M- W
6 [7 p5 c/ S* O5 R: L7 u# c# U                        if(rect.top==-1)//啊啊啊啊啊啊啊啊啊,贴图竟然都用完了,没办法了,出错了
/ g) r4 c* G/ e: j6 B9 q$ _/ o& p1 x4 ?9 ?7 g6 r* ^" I" B
                        {4 O5 l1 a! G( \* f- U  }
1 _( P$ I, _3 k
                                LogManager::getSingleton().logMessage("你太贪婪了,用的汉字太多了,这是对你的惩罚."); ) p* }* ^' m/ e+ u* w/ h# ?/ [0 l

+ R1 W1 {" }" I& M6 E) [+ u8 Z                                return false;
, m3 X0 X6 ~( |* T" w: X- G3 o& p' I( C9 {2 ?: o- k& @& I! C, g
                        }
' M, c$ i3 u3 ^  [5 |7 x
8 |9 O" Q: a& d4 D8 v( H% `7 d$ K        
0 j7 O9 D6 A' i3 y8 B- k. z2 A) }$ I) ?2 y; h. k( q! g
                }
9 G" d4 y1 E) K, n8 r/ S3 l! V+ f1 i2 b3 C, ]/ m$ `9 k
                        
+ j" [5 k1 P/ p) i4 x9 D: V8 G4 w' E4 k  {
               
+ n- m1 K3 Z! p0 F
$ s3 J3 j2 j6 |" Z& _5 z  e$ M, V                  //以下画字的都是招葫芦画瓢的, ) m) r0 h" p0 Y( T

* q2 Q$ R$ j: u3 X& Q& ]                  FILE *fo_def = stdout;  [5 l% X  _/ o- e$ |( r8 a+ w
1 i: r" L9 L- H
                 FT_Error ftResult;; s' S# C$ R1 y9 u% ]
& T/ {0 S  h9 e5 i+ W8 @8 ~  ^
  2 N/ O1 D; W/ p. i, p

8 R6 Y0 L- O( J3 U  e( Z            // Load & render glyph * Z# K2 {1 @0 N1 b# n) j% l

; _( [5 y7 c8 h' A/ [2 w                  
" w/ g5 {$ p8 ]0 ]( u$ m# H2 Z, f$ p. ]- \' F- R& Z2 B
            ftResult = FT_Load_Char( mTTFMsg->face, unicodeMap[dwChar-161], FT_LOAD_RENDER );//读取字体 " S- D2 M- a4 h6 Z& q- D
. p& E- O& R4 {* C" G2 l5 `( k
            if (ftResult)
% ?2 `3 J! H* T+ Y( `9 Y: t4 O7 J6 W. T( B5 N0 x7 q
            {
! ~7 x8 x4 D" h; o1 j
5 G5 ^7 b6 Y# ^3 w4 L: v                // problem loading this glyph, continue
( n, H; s# H5 M7 Q$ k. {" c1 r6 J' M" e) C2 `- Z( k
                LogManager::getSingleton().logMessage("Info: cannot load character " +9 X3 C0 T1 P6 q  o1 M

8 n: m. }# y, J6 `                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);/ {3 G0 z0 D0 `& I8 q

0 G9 P( {$ s- k                return false;//如果错误跳过
: i5 Z7 N% O0 z$ k" ?; w+ k8 @1 \, ]& S4 b7 P
            }, i4 N" d$ o1 S' ^6 l( Q
$ \" K' [* |# c! c  [' ~
  
+ O* j7 t' M9 I8 n9 Y
6 [$ j3 n- |  N4 Y! {" p          unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;% p7 J) m, N2 }$ d  q

: g+ L$ L9 b: Q0 n! I                  // 位图指针
2 X6 ~( P9 I' P5 q, {) t+ V2 r: f# i: W( K  R- E% O7 }
            if (!buffer)1 g( a9 e8 _/ n+ Y
1 m" c, I- C9 P0 ^+ ~+ S
            {
' t8 }, l: w: X) U
0 d8 `& i3 a  v1 J                // Yuck, FT didn't detect this but generated a null pointer! - X' o* c6 |. _2 t' Y
8 `5 [1 W1 O( ~! _- n
                LogManager::getSingleton().logMessage("Info: 1111Freetype returned null for character " +
8 b4 ]" k( m, \6 Q" G: i2 J
  o6 ~! I* g3 w  q2 S7 \8 {                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);) D. ]1 i5 p  a, \7 ^2 j3 ?- x, j! N
9 N& H9 X5 f% K6 }; T& p! d
                return false;//如果得不到跳过
  P$ l! S9 \1 _" G/ C% P- e! S
1 R- Y8 m' v: C: A& p7 r2 A            }( g; P' f6 X# d- l

0 @7 K: i6 |! M- b$ ], o" F; F  
- p9 G3 `# e0 L% x  E5 d
* j+ [4 q" G3 C                         int y_bearnig = ( mTTFMsg->max.bear) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );5 V" w$ v9 z2 e
+ p6 b; g: g) z4 e) k$ p" s+ s  G
       * E0 t: J+ N* q# l6 t
  g( [! z: {- J/ C6 \
                        4 v! p' _" K- r- U% ~! |" v& J% s

6 d3 o, Q7 {7 @            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )( m9 _3 X& a8 g: l2 C6 K( K+ y  e

4 Q  u: M) W/ \% M0 E            {
9 g7 _1 v# u% `; `; ]5 T; K+ s. `8 S7 ]- z6 @. w. z
                int row = j + rect.top+y_bearnig;5 o" j# G5 J  V& w1 h. @% T
( [; z. v" V( x+ L, E) I
                int col = rect.left;//列 ' }6 D9 D: J+ \  O
' P+ \% ~. ~5 t2 @! ]
                                pDest=mTTFMsg->imgchunk.getPtr();
; [7 _/ Z; I- C* L0 \$ W# {" b8 z0 u$ |  H' Q
  
$ V9 ?. m* G# V% m( D4 h& N% V: m- }* S$ i  r0 P; L" a
                        
* o4 {6 m+ Y% I5 }$ Y
* r& D! m9 x4 `9 Q6 m, P                                pDest+=(row * (512*4)) + col * 4;
! j4 x- x7 z- c. H: ^: n$ s6 d
" H( X6 W+ r4 |  ^& @+ G- }               for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//每行的点
$ A0 m5 l* Y8 p( P4 b
. j9 ~3 i, H0 j                {* H* V8 y( n  e0 ^' J
. a" c/ `. \1 ^0 Z0 j2 _
                    if (mAntialiasColour)
6 }+ H; g  H3 M6 R7 u6 O0 `# P) b3 n5 a
                    {& v6 T7 {8 N! _0 s0 U  {- H7 O9 p

1 L' c: g+ l$ i# U: X0 ]                        // Use the same greyscale pixel for all components RGBA ( ]2 j# l% q: j( t
" v: X7 e+ o" ^, ?( H
                                                        *pDest++= *buffer;
, ?. ?9 R2 a  O$ k& |) ?" u. I
" W( d! f/ R5 D' J                            *pDest++= *buffer;) G6 m! ?: X2 E2 S. j) C
4 ^$ d( ]& @0 q/ H
                            *pDest++= *buffer;& Q. Z: T' z1 |3 Q/ ]

+ t  r; e% S+ M& E0 S2 u4 j                    }: `4 C. L4 R3 f& j0 x5 u

4 W% w, x  c& U/ z) @0 h2 E  L3 y" Z                    else 0 N, s" P; x& R4 Y7 e% c' b' t
- X) t; Q2 h4 ]" l% G7 {% @
                    {/ ^. Q3 r- q$ ?7 H/ T# @
4 u  ^* O& i8 j5 V
                        // Clamp colour to full white or off
8 X, g* X, E" N% e3 ?
& G4 G0 S6 R5 U( N3 J8 a9 Y: n                        if (*buffer > 0)3 W/ o' S: U9 W
, h2 K# L! Y# s' Y  `
                        {' G- V2 O9 W! M: E! c) Z
! w6 }0 c5 T! S+ I1 A: X
                            *pDest++= 0xFF;
3 [. {, w( g3 K8 A* r
( Z, I$ ~: }  W) v7 A+ h- x                            *pDest++= 0xFF;: A* K1 h7 W& o0 B  @3 P

0 R- @2 K' T2 J. v+ Y1 B# o& p8 F                            *pDest++= 0xFF;
. R* n) S. ^% j# C* M8 q& w1 ?8 F; L+ M9 ~* ?
                        }' |8 p6 E7 j8 E. Q

- X. ]& ]% q" i# ]6 F                        else
- c0 A7 [2 X& h% P0 I$ s+ Y$ r7 M$ `% D# I4 G4 E, a
                        {. A  ~% Y( O( N  V, v/ d
: K' ^  T1 r$ E' P7 D
                            *pDest++= 0;
# f" J( K; |& h, Q% T2 @- i7 P
& Y# ^- {& I5 P8 Y/ U% A8 W                            *pDest++= 0;8 R$ `, N7 B  t9 q
4 M* _/ V. g/ G' W8 B
                            *pDest++= 0;; T% S9 z! o9 y: `& O
. r; m0 d/ T: s* E0 P- G
                        }
+ |9 a3 q! {  ^: n0 `8 C% X& i" `
- r/ [  @0 o  H* C5 O' Z, O; Z                    }
/ r  V- c2 N, \8 S5 k! ~
  `( y( H' b+ Z8 X8 W; g8 d2 U                    // Always use the greyscale value for alpha , y" b( O- `' p% Y7 j# B

8 a& U5 z0 w- m# _! x5 F, q                                        & K/ H- D) I- J1 ?! I
- f7 N3 O( Q5 o3 \$ p
                                //      LogManager::getSingleton().logMessage(StringConverter::toString(*buffer)+"is cool");. P9 x5 j7 y- S7 u2 Q7 e- c
, Y/ o" d8 i) [" R7 l! c2 k5 y
                    *pDest++= *buffer++;
6 X8 ]1 X5 U! U8 _) D4 \( y) _* W/ J- K5 b
                }
, z) R! E! R- Y# e; ?' P$ N* _6 d3 J
                                : d# [  c! b. |4 A8 U; G( |+ n5 n: a% T: g

1 G' |* R; f" K                        }
. j, R! R& J/ z" [' @. V/ N0 I4 Z0 a0 k. ]. y
                        // 设置位置
4 y: r3 z; a! u9 }3 h+ u. V
6 }% ^  t+ O* Z* F9 {( ~7 y$ [                        this->setGlyphTexCoords( dwChar, 1 H% e' \4 `6 B6 K
6 ^$ x5 L- Q) B& \# E( g: ]$ m
                                 (Real)rect.left / 512.0f,  // u1
& H6 {$ M3 S9 x  Y* W& w/ w
. y1 U5 E: @* d2 U                                (Real)rect.top / 512.0f,  // v1
2 y7 o2 ^0 [/ ?, A: d6 h4 L7 Y/ a
# w/ b! T: K0 N8 s7 I; Q                                (Real)( rect.left + (mTTFMsg->face->glyph->advance.x >> 6) ) / 512.0f, // u2: K9 u/ l% ?: p6 {7 }# ~
. q/ N0 c; F# f
                                (Real)( rect.top + rect.bottom ) / 512.0f // v2
+ b5 P4 m! u1 [5 }( s1 _. \- D6 w0 M- n/ h
                                        );
$ P" c. j  ]: u" A0 C9 j: L# F& W1 a/ ^5 s& z- W) v7 {# ~
                mTTFMsg->dirty=true;//贴图需要更新
8 b) q. S( Y; ^' p, ?" a' ]0 [- H# C! N* R  m3 R% _+ _
                return true;2 _4 e- ^: n. ^% s0 a
3 T/ x) i  Z  Q0 z7 h3 F( Q; n/ q! f
        }
& p; a* ]& }' Z8 n) v7 `0 ^% A( G! N
  * E1 p5 q& x2 a( N! A) w

9 U. A2 n5 n4 B7 v  J. U! q6 K(4)
* l, s% A3 z1 r$ G
+ g% u4 ?4 c7 u; A# j  F, R        松口气吧,繁重的工作都做完了,就是更新贴图了。
; F$ L, L  y; j$ Q) K8 R7 F, U
. @0 X9 @9 j$ e        Font类中~
6 M8 H' {- ^# f1 ]# ~1 r4 z- y) P+ o& J( {6 w
        inline void write()
3 l! X; x. B/ b8 R3 r  d4 a4 H2 L' x. U/ k
                {1 _+ `4 [/ b0 N5 W) J# m7 g

! Z& ^2 `9 P, `  l; Z9 q4 l' C: `                        if(mTTFMsg->dirty)
4 n* x/ b: H$ a, I# O& G& d4 [) f) f4 u
                        {       4 H; l# k. v# i" ?7 m8 @: Y
# t! J" s# x, B1 u* D; l
                                // 重新载入贴图,顺便说一句,类似功能的函数还有 5 X5 o7 o; P& g- B" e- E

: X7 X% p  v; r) |# q5 s+ |                                //virtual void  blitToTexture (const Image &src, unsigned uStartX, unsigned uStartY)=0
* j7 u: E2 P! ~* r  C- u7 U3 N  ?+ Q$ V9 t; `$ Y' R$ L' [
                                //和virtual void  blitImage (const Image &src, const Image::Rect imgRect, const Image::Rect texRect)5 j; c/ \2 M4 }- t1 p

) O* ]7 @) y' n& |( V                                //不过blitToTexture()在ogre-win32-v0-14-0之前没有实现,没有尝试使用。 blitImage()就算到现在也没有实现。
6 X$ [* h  e  B
/ L& [" ^: y' @9 r  
3 p/ {' j) N2 ]7 d. M) E5 h+ V' V) R. e- o" A
                                TextureManager::getSingleton().unload ( mName + "Texture");! {6 @# N6 D- p' [
) h7 T" G% a1 P& f
                                TextureManager::getSingleton().loadRawData ( mName + "Texture" , mTTFMsg->imgchunk,512, 512,PF_A8R8G8B8, TEX_TYPE_2D, 0  );1 G# T' i% D7 r- o5 [! o- \6 u. E

' ?! ~6 u+ ?. H8 n& A                                mTTFMsg->dirty=false;
5 N2 C0 H+ L& a5 Q4 J2 q2 W2 a: [' S  Y. o9 n' F$ i/ w
                        }
( s- j4 l" R; ^* S9 C6 A4 @- Q% M5 R0 D& V1 R. ^
                }
# [1 F( b9 f! O8 u
7 |4 }0 M' v& b2 h- l3 F$ w6 e) S  - X# G, k1 C8 A1 ~9 |" [7 R
7 }8 M7 u) D5 m2 @) _9 q2 _+ o" n9 B
         在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。 + J# ]/ I  f& K/ I; }
) D2 t' E2 b2 c0 I/ h2 v* [! i
  . ^$ }, ?, E, A; O
, S0 t8 L' A& P
  8 @& X% u/ _. S* A

+ l+ O# k  {' n( x7 h6 x9 M' I! p4.结果。
/ W2 s9 s* t# I# @  Z
' q# P8 h: K' \3 X( V8 v        好长阿,写了好长。虽然多是代码,但写注释也很累啊。重温了这些天的工作结果。就像上一篇一样“在OpenGL和DX9.0中成功的支持了中文,但是DX7.0中竟然出现了运行错误,具体问题还不清楚,还望各位高手指教。”。不过本来OGRE就不怎么支持DX7的,不管了吧。OpenGL中渲染的比DX9.0清晰,是我的显卡的原因么?以上的winXp+vs2003.net+艾尔沙980se通过~。。
3 i; g+ p  i) ~5 @
% V$ N+ y1 t# W. {/ T! ~* Q        顺便说两句,上次发表了拙作,没想到好多朋友和高人们找到了我。甚至联系到了一个南方的公司,说要做一个引擎支持中文的方面。但是卖完400多的火车票之后竟然因为住房问题作废了,5555,退票少了80元啊。还是自己差阿,如果再多学点可能就能要我了把~。努力吧,争取写《让OGRE支持中文》三部曲。 2 y6 V" R: `6 b/ g
, t* o  h: e9 H: N) Q# G
        下一篇应该是《可以输入中文了》。 & m3 v. K* S& w: |
  l" y6 ~2 z. E" f% f/ n
        也可能写不出来的~~~~~~~~~~~~~~~~~~~~    2 o) Q. G$ f: G$ Y: ]
8 K; [" {- d6 K, g2 K0 F
    相关文件 $ \; D( i* q  i. R1 \" R7 W

7 r6 i4 O1 l% T  ?" s) a$ u  s    chinese.fontdef//字体信息文件 放在资源文件加中
3 t/ f* D; A$ @$ d, n' F7 Z  N5 f* |8 Q6 J7 s
    font.png//字体图片 放在资源文件加中
; }, z3 p" g  z- R$ j" G6 B) H$ e* L6 }4 ^" t. h
  ) J( d; @+ V% _2 e) U2 ~

2 T8 h& X9 d1 w& R/ b0 z    OgreFont.cpp
& E# a/ F/ P, y4 C& p: U) m3 O: i$ h# v. i
    OgreFont.h, \( H+ P4 l* m1 p8 Q$ y

- T4 p: ]4 {. k0 }7 M" L0 E    OgreFontManager.cpp3 C. j1 h. g- @; ]4 z9 _
. g3 e0 O  i1 |, p& }! ^0 K
    OgreTextAreaGuiElement.cpp& U. Z! W! `" ?, {" @) p+ k

7 O7 S0 x: x' E1 ]. x: R    //上面文件覆盖同名文件 就可以 先备份
! L5 Y8 E% \2 J" l" m. x/ ?' u1 p& ~* {: R1 r; r5 q0 F1 b8 ~
   1 Q6 Z! b4 f5 E7 j2 x

0 k, U4 @! R! V8 N' l- Q   solo5.ttf//这个是一个中文ttf 我直接替换了原来的ttf0 z7 K2 O) h' W: k
- D  k+ {3 r/ i, f' q/ J0 @
   unicodemap.h//这个重要,是换算unicode码的数组(文中提到)
% [- n, g: g, A1 Y8 l6 K0 j: ^4 x+ F; r, W0 d3 j
  1 g9 l( m/ C$ {$ u- {: }# K0 A
. Q0 m! ~  ~; ]( L  o5 a8 M. b
这个是在ogre-win32-v0-14-0基础上改的(上次是ogre-win32-v0-13-1), 1 |0 M$ i5 a; ~$ s, Q+ d

' {2 z1 }; Z: q4 S/ V, Q请到http://sourceforge.net/projects/ogre/下载 7 q( d  @$ p+ S* @# m5 Y/ R3 z
' ~% ?# `/ B* C. ]+ v: q2 \
配套档案下载:http://www.gameres.com/Articles/ ... /ttf.files/file.rar
& B$ s6 G) W: I/ u+ @4 X1 l
0 d7 _) }; h" j 免费打工仔QQ:1850070
0 R( A5 G5 m2 v
6 v0 ?# H% l' Q4 x9 ^1 n+ ~From: GameRes
: n% \. {& O9 z! v! {" Q3 D2 I9 R' f: E" c  G! C2 q
http://www.gameres.com/ W# B& K, ~8 C7 V- E  z! @4 x1 O
5 m) C! g+ F! S% [
上面图中“免费打工仔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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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