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

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

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

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

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

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

开源的图形渲染引擎OGRE(3) --让OGRE支持中文TTF字体
( n. a0 i. f$ G9 }
% V0 D7 S: t% e0.还是前言
- A; ]2 m, m6 C( {5 p' w4 ^* Y' Z* Q1 r. V0 W
        如果你希望能看懂这篇文章,请先确定你已经看到了《让OGRE支持中文》(http://www.gameres.com/Articles/Program/Visual/3D/OgreSupChn.htm),因为本文是在上一篇文章的基础上写的,并且假设文件都已经按照上一篇文章进行了手术。但是如果你只想简单的使用TTF字体,只要下载本文附带的文件,重新编译就可以了。
2 W8 K* ^3 @4 p' _
6 s6 p% j- @: f( V3 |/ e/ |) D! n1.检讨
% U' O6 H  }: E3 h4 f: [- Y+ ]7 I; f  p, _
        正如上回说的,我们已经实现了一个位图的字体。但是当冷静下来思考时,就能发现这种方法的诸多缺陷。读入一个2048*2048的位图,等于在显存中保存一个2048*2048的贴图,不说是否所有显卡都支持这么大的贴图,单是每个Font字体类吃显存的胃口,就足以令人心惊肉跳。如果定义足够多的字体类,我想你的游戏的配置要求,在某些方面足以超过《DOOM3》了。
2 Z1 h* I! m( n& X% d) [. |+ J* q  u5 Y1 K* |/ f, X& X
        而且这并不是唯一的缺陷,文字大小相对于位图大小比例相差太大,导致浮点数的文字位置误差很大,你可以在一个文字旁边看到其他文字的影子。(虽然可以通过增加文字间距来解决。)还有点阵字体本身的缺陷,就是字形单一,不适合放大缩小,一些文字边缘的马赛克,足以熄灭任何玩家的投入感。 % d0 l  e6 h" R  X) \! G
& C& \3 |7 V3 M
        似乎TTF是唯一的解决之道。 1 U8 j( t8 d. \3 [

: M, [  f6 b' O/ R- ^" [' ]7 Q2.基本知识 8 K% O& g. l- k5 H/ H; ]# V
5 K9 A5 a& j) f% f+ Z8 I
(1)TTF字体。 . F) g3 d, w/ b4 j0 a

* d8 k- l' O; r, `' \        TTF是一种矢量字库。我们经常可以听到矢量这个词,像是FLASH中的矢量图形,在100*100分辨率下制作的flash,就算它放大为全屏,显示出的画面也不会出现马赛克。所谓矢量,其实说白了就是用点和线来描述图形,这样,在图形需要放大的时候,只要把所有这个图形的点和线放大相应的倍数就可以了。而且,在网站上有很多的TTF字库可以下载,或者你可以去买一些专门的字库光盘。然后在你发行你精心制作的游戏时,可以顺便捎上这些后缀为.ttf的文件就行了。包括Quake这样的惊世之作,也都是用的TTF字库。   Q% Q% R9 z' w+ Y
) i4 ^% j% R* T; I: ]: i
(2)FreeType2库 8 u4 _: W; g3 G

7 E8 L, M( ~7 l        在http://www.freetype.org,有一个FreeType的免费库,而且是OpenSource的。它目前有2个版本:1.0和2.0。其区别在于,1.0只能读取TTF格式的,而2.0支持更多的文件格式,在使用它之前请详细阅读所要遵循的Licence,以下是摘自FreeType2.0对字库的支持列表: + y2 T& A) y! f0 T" [6 W: J2 J
' }5 O5 ]7 W. N' G0 _2 R
        TrueType fonts (and collections) 3 s  T+ ^: }5 M" y5 }8 S1 ~& [

( j% Q2 V, k$ b+ H0 }        Type 1 fonts ' p3 Y/ t7 V- f, D

; d2 |; P6 d$ P9 k! m; A: B$ I0 z        CID-keyed Type 1 fonts & ^" Y* B" k0 g! p( S

( w- R! a9 \9 u% j& ]0 N* O' r9 l        CFF fonts $ e; H+ `$ }  d9 v* }

; q- X" [3 g! [/ o. m1 G6 v        OpenType fonts (both TrueType and CFF variants)
+ `. m, B% x' a+ e5 [0 D# f' z. A6 x
        SFNT-based bitmap fonts - _$ D1 ]% h5 z) E
+ x: \- W/ t! [* w
        X11 PCF fonts ) A9 r: c! n% [) I
. D2 o# H$ t9 m
        Windows FNT fonts ! z0 y$ f) C( S

3 f% e  X. J* P3 j* |% V(3)“主体思想” ' {  w- E# `7 U5 T1 t
4 q; F' h1 g4 h& V+ m
        请参照炎龙工作室的《游戏中汉字显示的实现与技巧》这篇文章,可惜使用的是Windows API,作者千里马肝,上网上搜一下吧。
) k# I! u% s  W. D  O: y) k( N
8 ]  h3 D$ U2 Z+ I        附带说一句,上面两条都是直接从这文章中剪切下来的,>_<  不要骂我啊,不知道算不算侵权呢。
5 s) `3 x% w3 c* g5 A9 s
( M8 [0 v/ K: F) m/ Q3.动手术---比你想象的要麻烦
' ?! X7 `9 E) {9 n" ](1)
7 V, u( m7 E- [' T% E& |        首先要告诉字体类,我们下一次渲染需要哪些字。以便字体类可以在需要的时候释放不使用的字体。
9 T* H5 ]/ E0 R' x5 E
+ ]: U3 E: k5 i! z/ h7 s+ S        在Font类中~
  h# Q# z$ N8 m% C: l! ^2 p
. h  Q/ C% C' {" P& U5 z6 v. f        a.增加数据 bool mUsing[OGRE_NUM_GLYPHS]; 用来标记文字是否使用。   U. n4 |7 ~" a6 ~1 ?% ^1 T

* {9 S2 @, r8 c5 @6 \) [' t( F        b.增加函数 3 i9 s' K3 M1 O5 k" U
9 z/ ?3 ?$ {8 O1 W; P
                inline void setUsing(std::vector<unsigned long>& caption)
7 y! L: `! c. v( E: i7 |6 i2 F
5 U& E, b2 k* G  S. v* ]                {$ j& I9 G  [4 t7 L0 r. R
- \* H: p2 `. Y; i" o5 E
                        memset(this->mUsing,0,sizeof(this->mUsing));
1 M5 r! U  n- B6 a7 ]( l7 S" a/ Z& O# V% {6 u' w, u
                        std::vector<unsigned long>::iterator it;+ z& @" k) X8 W3 s' G/ u0 F- k
7 K8 j* b. I1 j8 h* ~# o' V0 E
                        for(it=caption.begin();it!=caption.end();++it)- J' k% X9 H4 ~* u

; H6 M: |% F: `* v                        {
& l, Z4 O/ K* K7 I4 V* d" w* U/ `% d5 f6 h8 l- G
                                if(OGRE_GLYPH_INDEX(*it)<OGRE_NUM_GLYPHS)* ]& z; x: K3 ?# _$ n
. |6 T/ l  S2 ^$ D* V6 k
                                this->mUsing[OGRE_GLYPH_INDEX(*it)]=1;//标记文字为使用 + P+ p9 k* L$ N7 F) j: ?

+ ^9 z( u9 g. A( b6 n9 F, K/ X                        }
5 \$ t& U( J$ s/ x# x- O$ w6 E
" D4 H. A" s  K                }; i0 F$ j# b3 q) |7 y7 ~
0 s) R& T% }9 J: u2 d2 ]7 J
        并在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。
5 ~. @. Y5 c. F% F* N9 u(2) 9 f4 U4 \8 _6 m" w! m* Q) n
7 i4 ]+ q2 ^0 |/ S
        然后是修改void Font::createTextureFromFont(void);
0 T! n" ^. g. Z% t( Z7 G' D2 Y  {  g$ }" L# _+ ?- l$ ~& Z9 ~( D1 y5 X* f
        Font类是通过void Font::createTextureFromFont(void)来把通过FreeType2分析好的英文字画在一个2^n*2^n的贴图上,然后再保存英文字的位置。 % x6 F5 q1 }0 F5 y4 [, \. l

7 U1 L8 T5 H( k1 @2 C" Z) @        我们需要修改的是: , _; d  c/ P; J1 ~) e( u

, ~% M) p! Q) w: w5 Q1 H        a.从函数中分离并保存画字的FreeType2和辅助变量。我们通过一个类来保存和处理这些变量。 ! ^2 E! {# D( v9 W  l5 t
4 [+ g7 B) D1 @
        class TTFMsg4 b# E# d- J+ Z

+ g5 ~3 B# q1 K, z% b                {" H1 Z5 ]9 z- d, h
7 `& \; Z, {/ a7 V0 |5 c# {' i
                        class Max//类中类,用来保存几个"最大",6 P% A  O' U1 W* O% i, Z

" f% ^/ z; q$ M                        {
( `* x3 b3 n3 P
! R( z& P6 j0 L' Q7 A                                int nothing;//这个是用来占位的,没意义,反正没他就运行出错,可能和数据对齐有关吧。
2 O+ e2 ~% i1 `8 i
5 Z! D. ?. ]& Q! C                        public:
+ E; v2 L8 [- p& ]! N6 v* ^                                int height;//文字最大高度 5 \4 T8 m; F- P
                                int width;//最大宽度 - D7 w8 c- r) [! ~' A* Y
                                int bear;//最大空隙?
3 c3 b1 o* V0 b7 \                        };& f" D4 N. V0 A% n( r
                public:5 j$ X$ ?" s5 @, E+ O* l! Z
                        FT_Library ftLibrary;//FreeType2用
' V  A* N0 k, ]: y+ u                        FT_Face face;//FreeType2接口? 0 @4 q- `' \8 E  _
                        uint char_spacer;//文字空隙
  a8 l7 Q+ ~: ~, M- P                        SDDataChunk ttfchunk;//数据块,用来保存ttf信息
9 d8 [# J) g( ^# s  l                        FT_F26Dot6 ftSize;//FreeType2字体大小 & C# R8 I# W; q  d, R
                        std::pair<uint,uint> point;//在位图上画字的点
$ H9 ^9 z+ j3 T8 {                        SDDataChunk imgchunk;//数据块,用来保存位图信息 - h6 o5 U# `6 W- S8 o- }
                        bool dirty;//标记,看是否需要更新贴图 ' v7 x! c& Y9 {) B
                        Max max;//几个最大 2 N( p- [8 U3 \1 ^0 K

2 ?* J6 B, A/ V! s; q  R9 n0 A                        inline bool init(Font*  font) //这个是初始化函数在void Font::createTextureFromFont(void);中调用.3 |- f/ J+ x8 p5 c7 b+ s
5 d9 y6 b" [9 b) [2 _+ k
                        {      
; b( A/ I. E% }$ z
3 m9 G" t) j; M1 Q" [" W6 z/ {                                //以下都是初始化,大部分都是从void Font::createTextureFromFont(void);移植过来的 5 b- T* V4 e. u( v9 c" M
# {- |1 q& e( g
                                dirty=false;) U# u! g1 D/ v- r# V6 Q( K

( L; ?0 d8 t9 u& [$ E                                if( FT_Init_FreeType( &ftLibrary ) )
: `: L) z- t- N" B. |, [- u- M8 S3 _# W2 T
                                  Except( Exception::ERR_INTERNAL_ERROR, "Could not init FreeType library!",
7 r8 c' Y( m$ j3 w, {: _5 d
! w+ {1 L2 I( c5 c3 \                                "Font::Font");
/ }8 f$ E% Y3 K9 N8 E* i4 ~9 Y
               
( B( T" s4 w" x9 w1 I& R
! D' n. U% \8 x, l- C% w+ o% S( q$ |                                char_spacer= 5;
5 ?9 Y" I* y  Q# d: L! n+ U# w; m0 u5 |0 t
                                FontManager::getSingleton()._findResourceData(font->mSource,ttfchunk);
' ?* a! o& [3 d  n; R( i2 D, I
' V* m$ X8 Y! N1 T5 |* ?" ]$ Q7 b, W3 g                                if( FT_New_Memory_Face( ftLibrary, ttfchunk.getPtr(), (FT_Long)ttfchunk.getSize() , 0, &face ) )
) u, f  c3 n! u! V6 m5 x6 z  P' [/ b; }8 D
                                         Except( Exception::ERR_INTERNAL_ERROR, & P5 R4 }2 V: w6 U7 T( v3 Q
. n1 f; |( {. Y2 @' o" \. v
                                        "Could not open font face!", "Font::createTextureFromFont" );' f4 s8 [' A! o
  ]( @' G8 O4 y& d: Y
                                ftSize = (FT_F26Dot6)(font->mTtfSize * (1 << 6));4 Z/ D/ p9 g+ H/ k
( j& U) ?# Z$ y# @/ _
                                if( FT_Set_Char_Size( face, ftSize, 0, font->mTtfResolution, 0 ) )) }9 n5 b1 x/ F, \
1 J+ l+ I, {  D  ^& m6 U
                                        Except( Exception::ERR_INTERNAL_ERROR, " F5 f" o4 e" U2 ~4 K2 m

3 I2 S! v3 L, d0 \" Z, }3 U: c                                        "Could not set char size!", "Font::createTextureFromFont" );- ]* g! i- S' r9 J- `: q) t0 F  e

7 y% r% _; J( G6 C  ( K! X+ t" b2 a/ y2 p$ P; C

1 `' S+ I# C6 v. Z                                return true;
' m1 F( r) S+ |" W* d& {$ c! \( ?( K& O5 i" B& B& C
                        }0 w8 x, Y; c2 U) A/ \0 t( c
  b% U1 l! J! V& ~! e0 A2 D" o2 l# X
                        inline bool done()
  z" d8 q3 C8 I: t
3 o- z4 ^! s$ e+ ]1 i" }$ T                        {
( ]+ v# E. ^: O1 n' O
0 @0 z4 P* K2 k( `# R                                //在Font的解构函数中调用的,本来应该调用下面两个函数,但是不知道为什么一调用就出错,不用倒没事。 6 U4 S! O6 n6 @4 U( x
8 L/ X$ p9 M- ^$ b8 q% A
                                //FT_Done_Face(face);- T+ v9 c; M& z4 W; b3 D
& D' d$ s8 T6 ^( m' p. d  I
                                //FT_Done_FreeType(ftLibrary);0 o& p& V8 g: X; s; t
5 J: `1 c* h; H9 [7 K+ `
                                return true;
; a6 F& }6 q6 n4 m1 U: L& l5 k1 g
3 O9 `8 C; t5 U# p) l                        }
5 v" a5 x: \9 q( ~5 D" {$ P$ d3 B3 F8 J. y" N  x+ W
                        inline bool getRect(Image::Rect & rect)//这个函数以后用的,是用来找到可以画字的贴图的空的位置
) B2 [" b: n6 r5 g
) k* E$ S' v, w7 J9 {7 h                        {! K6 {" p) B) W) J% D  [
" C' ]& }7 Q4 ]2 v! l8 K) K
                                if(511<point.second+max.height+char_spacer)
5 }" X, E+ Q& z4 R  y3 M' j# E4 I* F# U# X- E! c( Y/ x
                                {% W: T3 d/ \& P

/ t( j, `8 n2 a! m3 v7 c6 x' Q                                        rect.right=rect.top=rect.left=rect.bottom=-1;( E0 ~  m0 B" X" n! ]( E8 F

( [* F: _. O8 E                                        return false;
. H( w; @4 z  C1 m7 f$ t0 |
* {" o2 m/ M3 z                                }6 c: M) e6 ]. o- v5 b" N" x  ?
# E7 U" \2 o* l2 Y( a, Y
                                if(511<point.first+max.width+char_spacer)4 Y+ S& O1 ]9 |% w
1 T: v: S" j: K7 h: d( t! G
                                {2 n/ I/ t9 n7 e+ w* _
( l2 z; N  x5 S, B  I+ n6 z( ^
                                        & R$ G6 L2 D% {/ y3 H" R, j
. o) x3 m; W* I
                                        point.second+=max.width+char_spacer;
$ w7 H. Z/ ?5 U5 v
' N  |7 D# h; G1 K                                        point.first=0;
" b- e: v( n$ U! U- n# z% i
' R+ E+ V8 A0 \- y                                        if(511<point.second+max.height+char_spacer)0 z1 J8 A. O4 s
! ]% Q+ \$ o* m% k5 j
                                        {
+ o7 Q8 e! d; w9 b, B' y
8 e8 y  H% U% b3 E                                        ( E8 V. P( M. r& K
3 S4 g* K/ V; z# S8 v! I
                                                rect.right=rect.top=rect.left=rect.bottom=-1;
5 ^9 W/ P- p7 D
; V* O3 T+ @0 H" _0 [                                                return false;
$ z7 V; r+ Y5 K; j9 F
8 e8 [$ b! i% [) x/ F) o) \' f                                        }
, g: b5 b! t; d) w7 P: Z, Q8 A# W9 @4 @! \* S
                                }
( e; }; X: h0 e
  l: p4 O+ Z! [: x; r9 b, Z4 m                                rect.left=point.first;' a& e+ L$ T7 l" C3 M" M

$ D+ ^* w7 L% G& O" [% c) ?3 P9 ^                                rect.top=point.second;3 D* h7 H/ R& i5 j! k4 l  @

6 F9 b! E" b8 @                                rect.bottom=max.height;
( G: P+ v) o+ \3 \9 R, ]5 d) u6 u+ B8 w- q0 K2 m
                                rect.right=max.width;" v( D3 z% I/ F' H
/ w, I) }2 b. F2 g- Y/ c
                                point.first+=max.width+char_spacer;
6 e1 e1 d$ l! h" W  n  H2 D8 V  Z  ~, ?0 G$ |
                                return true;
3 E6 G$ a. e+ V/ H
" M: [# c# m+ h/ C                        }+ G) Z6 {& ^+ U0 J1 B. X7 X

6 d. f6 i) ?; _+ b3 _  j                };
3 e! p4 I6 ~$ B+ x" ~0 K( y6 }3 M" g. L: T( ?) A2 F3 e
        上面的类定义在Font类中,在Font中增加 TTFMsg * mTTFMsg 数据,并在构造函数中 mTTFMsg=new TTFMsg;
' @9 ~0 q. q4 X, i5 r' V1 p
* Z  E0 V6 ?+ ?: z0 V1 k        0 t1 D5 ~* ~1 ^0 C) x& g1 `

0 T4 {, C5 d2 p" ^% `        正是修改void Font::createTextureFromFont(void);函数,主要几点,首先是分离出很多变量和构造到TTFMsg类中了,然后是贴图从2^n*2^n变成固定的512*512,为什么要这个数字呢,因为256太小(废话了)。能保证512*512大小的文本区不会出现不够画字的情况(所有英文+符号+没有重复的汉字),这个安全区域基本上是够用的。(什么,你要画满屏幕的汉字?哪你自己看着改吧。)还有一个重要功能是,要找100个汉字,找出最高和最宽和最大空隙作参考。修改完成这个样子了~
# S/ g7 `6 H3 E. t; G* h6 _! {, x* j% G. r5 V1 ]/ X9 a
    void Font::createTextureFromFont(void)1 e& r. F2 `7 k1 R% y
  V7 b, C  h. c' d
    {& u8 O! D6 F& V# e( k3 i

3 F; V# e. k+ k8 i& X& ^        mTTFMsg->init(this);//初始化FreeType2
6 U, Q  z0 t* q* e4 i& c! ]( ?2 x8 D" @$ b! j8 h" a- a- v$ x) B5 Y
        uint i, l, m, n;
4 R6 E5 y1 V1 I5 o* ?% ~& L  ^1 k' L$ t3 E$ e/ a& b# ?  p, z
        int j, k;
3 A1 m& \) d- {! i9 q+ F6 T* V0 Q, d" m/ O6 \) T$ W# u6 y( ]& v! }
  
0 c0 b  @" Y. @9 b8 ^; q4 h/ X
# e1 s6 @$ m! h3 @& d      
2 M1 u1 l& Q$ |. ~/ u
  c5 {, o( D- f* ~: R        FILE *fo_def = stdout;//啥意思?我看不明白 4 w& `' k' p9 c

! ~* O! i; {9 G9 P. Y  Z# ]# e8 l  ( ?; K; E* J' ]2 f
/ E9 Y' \/ a" h/ R% }# Z2 y
        int max_height = 0, max_width = 0, max_bear = 0;# R% v: q& X7 j" U, H: s  y7 `
9 n/ z# ~5 P+ g" r5 t
  ; X/ e- V4 u. s+ Z4 S3 \" n0 s

8 h( P0 k) ?- T+ s0 `- O        uint startGlyph = 33;
4 D+ H- D5 r9 K% X& v
( j2 d9 z  m4 h' q& f& |  y, l9 @5 I        uint endGlyph = 167;' @: u7 k9 w" V# e
$ O" G% T7 F) u: y- B) r1 D% g. h
  
+ B- o4 h+ O0 m" q  I# _9 {3 t& O. z2 a. e! _0 S# ^( H
        // 找英文的找出最高和最宽和最大空隙
$ c: i( j/ f# G0 o3 G- _: l: ~' {4 {7 |# J4 M& z
        // Calculate maximum width, height and bearing
$ n+ y# j" D! P' [  b, q7 I- r2 @3 ?7 }4 K3 o8 d% M
        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )
5 m  |# b4 x5 X
2 k5 u- g, ]; v/ y0 N        {- P  x7 h5 I8 ~! |. l9 d  ?
- I. ]( X4 F; F3 H' f) S0 a$ \
            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );0 n- d5 j8 c# z$ ~! H# N1 p

1 N" {/ {2 ~) T; f* G$ f0 |            //以后的 <<6和>>6都是FreeType2中的数据和我们使用的数据的转换 : m6 `6 l+ A: W$ L2 c  d, l9 d

$ Q* p' {7 `' d0 d            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )
# j1 ~: s. P; _6 j& K4 T4 v4 F5 U1 a
                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );
3 C, m7 k8 I2 z3 H5 ^! }
& ]; {# N. C( ^) j# n            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )
$ q7 O2 E( V# |! u: ^1 Y2 A  H7 \; K9 t- K$ v" e% _) Q2 ~
                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;4 j- _5 G7 B( S8 K' {

' L) O/ t5 v; G! i* H4 g3 r- S  ; R- j9 g! Q$ `4 `& d! u# g
  I$ V& ~; ]7 `
            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)
" Y$ t& P) u1 H& c0 h( \
! Z% s( h4 |/ P8 H1 k                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );# N7 [: U; W7 L
6 o" e1 O" V/ S
        }
/ n1 O. L8 \; U( Z/ L6 R' y6 t$ F* c9 y  `6 L
  
0 L+ }$ l" p* W+ E& `: m8 _( Z0 J* L- S& U
  
+ C: m9 W. a1 g7 j' T* V" }
1 V& E% {+ o' a        //下面的for是找100个汉字,找出最高和最宽和最大空隙作参考。姑且认为最的汉字就在这一百个里了。 + X7 B) X; N! [3 y

2 U) ?, q' a' s6 N        for( i = 20643, l = 0, m = 0, n = 0; i < 20743; i++ )
% Q5 T" Y% D( c# Y% g! o% c3 a
& B( n7 g* [0 i" {! h2 w        {
5 |! n8 M# ^- ^/ {( q: i: _: J
0 h2 o6 b! z2 {0 a" ~            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );5 R& O% r  G8 ?* `
8 d: Y7 S9 L8 e' m1 K+ L% q+ H! o7 s! f
  
- ^% m# l8 r) Y2 f: c
0 b& u  P: c5 J, k7 ^, w            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )1 z4 d4 }& p! }8 |* _
. c( q  V/ d: n2 c7 l" s' G: ?
                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );
5 M$ N- `* v2 a, Q: F% p
! F* l9 ?7 {' a            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )
. _( e$ ?* ?5 G) i1 T* E7 e3 Z- m3 F
                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;: T9 x: E7 u" w) S, E% G

: V  y/ A! ?; U  
" K! s5 Z( `) h, J) f4 A$ P
  k2 x$ n8 y6 i9 h1 M            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)
/ _# \- {7 D+ r9 b1 z: C0 R" s: }, O& f, g5 W" x' Y: v
                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
! N. ?. t- E8 s" E
0 ^+ H# |0 d% Y% e  
9 e% k6 @% R& Y: j. m  A
; E- S2 N- }) C, ?/ c                        
% |# ~. O0 H% ~+ ?
/ M- f: P, C- E+ Q6 y            if( (mTTFMsg->face->glyph->advance.x ) + ( mTTFMsg->face->glyph->metrics.horiBearingX ) > mTTFMsg->max.width)
. a  x1 ?4 b2 J" f/ j
# Q2 e/ ]  d" M( F' W                mTTFMsg->max.width = (mTTFMsg->face->glyph->advance.x  ) + ( mTTFMsg->face->glyph->metrics.horiBearingX );+ I& @/ F$ L" D+ j$ d
. Q) E" y8 x# }" {4 O
        }
6 J, p! _  [1 a' e
7 i, q! Q5 t3 K; ^  4 f3 Y2 F& e5 R! I+ V. q5 P
7 X0 n: N9 G7 q3 ]8 d* q) @
                //下面几行行不需要了 我们要512*5123 d" W" ~5 A: F  m2 d3 U! B
; T+ J) N6 l5 {8 ?1 n! t' f- c
                size_t tex_side=512;//就是这个了 512) a$ B4 u( u. v1 [9 H1 j

4 w4 f' {; W' A/ ^* @+ p$ j        //定义数据宽度 因为是32位的位图 四个char为一个像素,为什么要位这么大呢,难道不能用8位的么,我尝试着改来着,不过改了之后就不透明了。望高手看看能不能改。 . J7 ^2 r7 x) N
- x0 R( g5 [8 S) j4 Y
                size_t data_width = tex_side * 4;: \8 k0 v! n- p$ b' O* T# O; Q" n: Q
" V, C9 V+ g8 Q9 I% F% _
  
/ r1 U1 \9 q  s( o- g$ H, f
9 C( H* o% ?9 g& ]2 C                LogManager::getSingleton().logMessage("Font " + mName + "using texture size " +
, g" K. r6 v+ v! e3 I9 w) N: X. E' O' g1 Z" a0 @
                        StringConverter::toString(tex_side) + "x" + StringConverter::toString(tex_side)); 7 i/ g( ?% d% O
  `+ d0 v* U! u8 B) j. A3 p" F/ O
  
0 |' {4 |1 r& N+ d6 A
) G8 {+ ~( `. B# ^        uchar* imageData = new uchar[tex_side * tex_side * 4];//设置一个空间用来保存位图 - k) E! Y' V3 S) G5 s& G
4 f, b9 [: W$ e$ K( }9 C. A' }
                // Reset content
1 K" k. Q0 L0 G/ x) E! o# Y( I; ^% D+ _) e0 |; r; g% y/ p, A) D  H
                memset(imageData, 0, tex_side * tex_side * 4);//清零
; b" n& m, c4 w" Z% e  q- L+ V! Y! N+ z, I
  
6 [" u) b! U/ p5 O* D
5 C9 l: X) N5 M, j6 T        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )//遍历每个字, # t3 b% p$ t; F
. F; y- o% |8 ~$ T" P" Y
        {
8 P. t- o4 t5 J
" ?' X2 p* s7 Q                        : |0 P9 k3 H. Z: w" F

/ N1 ^! }. m7 [  ~; i' A            FT_Error ftResult;+ V3 j6 P# @0 a4 M
- x( \8 J# v$ Z" n  W
  
8 F! i2 p% `' t. o* F, Q- v& W; ?
1 y4 w6 m: a9 z/ b9 u1 f' J            // Load & render glyph , x, G* |% E* e5 t

/ F  V0 V  v1 P$ z1 i9 V: M! R0 B            ftResult = FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );//读取字体
" W7 P& E& v7 X
4 [$ m8 }9 \- i, Q# K. H/ a+ P            if (ftResult)& }& R6 K6 l: C+ M

9 k3 N8 g2 a& {5 V4 k            {
% w1 D! v( H! l9 i! J$ `2 s" r6 ^2 q# k1 ]: z
                // problem loading this glyph, continue # l  N8 E: V% t1 ~* |6 a
6 W* `1 c" p" {/ M9 O2 [6 Y7 r
                LogManager::getSingleton().logMessage("Info: cannot load character " +9 m; H' t) t, {' w$ g7 Q1 f
6 ^( H9 Z- K6 M6 v+ @; b
                    StringConverter::toString(i) + " in font " + mName);
( t1 b( |6 n! k9 y4 r) Q% H
  Q2 \+ n  X4 d5 g3 |' M3 \                continue;//如果错误跳过 2 u  W9 @8 W- ~9 z( a( i8 m

& ~7 Z" y  W+ e# r8 e% _+ s            }
0 l7 @9 u0 n! W: g4 j# Z- I! G1 X0 U+ w$ W
  
7 O* N: c# J( z$ C# x6 l9 |
- x) Y. c8 X8 Q                        // 应该是字宽 $ N$ [/ j# o1 J/ V5 U
8 A) ^! z1 L, ?& I" L" [5 o; I
                        FT_Int advance = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
9 N" U- `( o# j2 @$ v& V5 B4 B8 [- ?7 C% x/ g2 Y; [9 O
                        
1 B$ _! e3 g8 {1 M- L$ k2 j2 b6 Y# A
7 M5 [/ X4 o$ v$ Q. \                        // 得到FreeType2的位图 - |! B7 X7 j' o- a

  l" {& Q8 V1 l  ]            unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;4 j) B$ P7 i* [

+ P* _$ z" [' {  q, B+ \  
/ D& y; O  Y6 Y# C
& G9 v4 C9 }, E, q8 f- t! j            if (!buffer)
0 P# d/ k+ \+ F) y% \; h
3 W! |/ a9 B2 d5 h1 `( |3 @. y            {
! D) ?' C' c9 w9 j8 W. r! Y
/ Z: {" {  i6 q                // Yuck, FT didn't detect this but generated a null pointer! - I* h/ @% }* ~( \% y! X! U3 a# P

* l* l$ U' b9 U) Q9 X                LogManager::getSingleton().logMessage("Info: Freetype returned null for character " +
) k2 Y: h! _' A5 Q4 s
9 [( ?# K3 @' K9 x9 O% V                    StringConverter::toString(i) + " in font " + mName);
( a4 U: Y, H1 w# r' \; [2 e3 H8 C) J3 Z* [( [/ g4 m" e0 P& S
                continue;//如果得不到跳过
! Z: V6 [) s* k" J8 v3 }0 S# _' M- l+ Q% y* T: P7 {, f
            }
3 f0 y& t5 U8 l6 A* Z% f# \" ^8 |5 N: A1 k
  + [0 l* X1 k# ]- ^8 v2 Y3 F4 ?

) C1 q1 E1 h' y                        // 得到y的空隙 (最大空-空-本字空)就是说空出这些字底部就平了 : @6 a7 a3 {( d# r% O+ w% l0 m/ n

) f- z. Q6 ]; |$ `            int y_bearnig = ( max_bear >> 6 ) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );
# L1 n- W/ }0 X$ i. E0 N+ D
6 o" Z$ Y7 |7 {6 {1 T( m0 o- _  j0 U                        
- f3 u7 k. v  H8 l3 I: g  q3 y- _( T! z. c/ T
            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ ), B0 L; ^. W3 o

! L  p* K; ]! |            {1 R3 j5 _+ K5 Y4 Z

8 K( l; y% {6 R+ G* g8 f2 n                                int row = j + m + y_bearnig;//相对行+本字在位图的总行+空隙
" F6 m: D' X) O9 c6 ?7 J/ t+ T
, W" p4 v1 Q% \' e2 z# I% l3 l# Z                int col = l;//列 2 q+ V7 K4 _) Y# D  u4 t+ w% a

6 _6 ]  S: C2 Z2 x                uchar* pDest = &imageData[(row * data_width) + l * 4];//找起点   $ X9 b$ i. A) ?7 Y! U9 W: N- Z
* s5 C4 f  j( P# @4 Q+ M: l
                for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//画图 7 L, Z& w( A( f/ V! Y7 @. v

" }- P2 g0 Z4 w                {
; `* w* A6 k+ a6 I$ V2 P  r) k* k. @1 g) }: _1 T
                    if (mAntialiasColour)//看不大懂,难道是灰色字体?
. I, x' l4 t/ T7 I0 P; m  ]# Z! b3 w5 i: [
                    {  H0 d& L4 D! B% A/ y% G

3 l% h9 P3 d8 q" \8 Z* V+ H5 z                        // Use the same greyscale pixel for all components RGBA
$ c& o3 ^+ [0 {% M+ C
0 ?; h4 @3 s& o& V, b                        *pDest++= *buffer;
2 K. g. R, v* A; T' F* ^6 L$ M0 D- P5 |, _; B1 n( }1 T$ p
                            *pDest++= *buffer;2 e; u( J! Q5 C
3 L3 p5 W1 H( |; O1 t$ E' ~
                            *pDest++= *buffer;
0 g& u: J3 t( s1 d, a& p6 O9 M! E5 A4 x. S
                    }
: p! o/ K9 m- B+ h, P3 Z) M* n' v( Z; w
                    else
) }# @% u* X$ H' ]# t' x! ^: C/ }4 i- t) S
                    {
( ]7 I) f7 M" h7 [8 V$ G/ f6 X
" n0 o* `/ m% y" A                        // Clamp colour to full white or off $ f5 j4 U% \* Z

$ b+ K) d4 o4 I/ d" Y. R8 ^6 U                        if (*buffer > 0)
- y; t& i/ p! c9 ^3 d8 Q
- }4 t  L( M" v0 y                        {
! P  K3 z/ |. Q2 u7 _' R
6 L$ L) Y/ k9 c. S4 b  ]3 f2 f2 h                            *pDest++= 0xFF;
2 g8 J) g$ I4 b0 \5 z- L
! z: Y1 b& F, G5 I5 }4 F                            *pDest++= 0xFF;
, ^- b+ b7 N6 ^1 X1 N+ J: {. v! C; r& G+ L5 H8 ?
                            *pDest++= 0xFF;
# i8 J; {# ~" ~7 Y! Q8 p8 w# _& `( V" w3 Y$ I9 T& S3 S' @3 S( o
                        }! ]0 |, M; A4 A: {. S$ b
& T( x+ H! E8 q, ~5 V9 R  S
                        else 7 O* _: t: S0 ?! j/ R

9 h; H5 N, V2 [8 H( Z8 F( z, p7 I' {                        {8 r/ P" n% p3 r6 ~6 z

- }- L1 ?5 S7 u, ]9 _: r                            *pDest++= 0;
4 l2 k1 e( T/ R& s' U. j( f$ q. b& r2 P4 v6 O' C7 @7 v3 S6 e
                            *pDest++= 0;
( r3 X& @& f( n! A# t/ d- h) k# j6 R
                            *pDest++= 0;+ R1 M* ~' K* @* P6 p! |
  I2 e5 n+ c# {- n, w8 O; @/ E
                        }% c  q. M2 }# R: O& K; V# B

/ T- u9 T  @8 {6 v                    }, @# r, c, T* s5 O
; i; E# D6 T# w* |8 Q  v
                    // Always use the greyscale value for alpha
# v! }7 C$ n& I. q' L' v  x
2 `! Z+ E; o- S; ?' ]                                        * g( h6 _  ~5 I, @- Y3 c. S

- W! O; o$ U2 o7 p  i4 [                    *pDest++= *buffer++;//alpha! 我是一点不了解了为什么是这个? $ C5 B# n: v5 O1 n. o) |: y

- v  g8 }9 c: e6 f8 U6 }                }
6 z( |& v$ R" x1 z- X) i& t& z9 y0 ^; o9 j- }$ d
            }, q; O) B5 R% {1 ^0 ?; @

' {$ _  w  V; n! o  
4 x2 R' m8 Q2 D. _7 E# n: y6 Y/ g. e1 x5 Y7 e- l* z
            this->setGlyphTexCoords( i,
7 l6 I& H0 a6 P! c, T- I1 u( f) j4 I" t; Y6 \
                (Real)l / (Real)tex_side,  // u1, ~' m8 m5 r% Y

3 ?& P; o9 l" ?                (Real)m / (Real)tex_side,  // v1
% l; H) `! L( s( L' \: a. D4 D" }5 v+ v5 z6 o
                (Real)( l + ( mTTFMsg->face->glyph->advance.x >> 6 ) ) / (Real)tex_side, // u2' g6 |1 `3 Z$ F0 z: K, k

) T7 x) y# J, }1 X; |                (Real)( m + ( max_height >> 6 ) ) / (Real)tex_side // v2
. c/ R+ `' p' o4 ]5 [. q2 y% n% C0 ~9 o: z* N1 N6 E
                );//设置坐标 $ R- U8 ?+ m1 w; R5 a7 ]9 r/ z

, C& g0 r$ A, Q  . d, ^6 n* ~$ o. ^
2 G% x2 N* r1 R  Z, C7 N: s8 a1 L" l
            // Advance a column
6 C: j7 X0 O1 D5 m$ S" R0 C) s- q! t, J. [+ v
            l += (advance + mTTFMsg->char_spacer);
" }/ T' {  T' Q# J7 K3 N" |8 z4 {; x. f1 \
                        //l+= 本字宽+字空
& ^; m! q4 x6 R
6 t: ~9 L2 f9 E; I  k; q  c* ]* D9 c  
% I5 }/ L, E5 s1 T
- a, q/ F# l; U            // If at end of row 0 V) a/ A+ s; V% h. l; h

4 h2 {) W7 J- m+ |8 J. a5 Z& D                        //如果到头容不下一个字 : ^9 f) {1 m' m4 H& A
# Z' q. p, ]4 r  b: X
            if( tex_side - 1 < l + ( advance ) )- D, L* g! W5 y+ k, |$ c- l

7 Q8 O& ^& H/ c; L% v1 M. v9 P; M8 y            {
- l5 J0 v! c7 ~) I9 v/ @4 O# r* b$ O: L: I' h3 _1 ?/ B4 v" G
                m += ( max_height >> 6 ) + mTTFMsg->char_spacer;
) z& u0 {; W& d5 W" `+ a3 v: Z) w& I6 i
                l = n = 0;2 ?8 {. G; F  U6 i" t" K
+ I. O" F) e/ C! x. _
            }
* \, B0 T( R# M3 r, T
% K, C. t- R# Y/ y  - |5 O5 L: b  w! r. r1 ?6 A, a
0 G, T) s2 }' w. G1 V1 }* \; E
        }
2 W. F( C/ b% c6 K6 J" Y2 v& Z/ |: v" q$ M
                // 把信息存到我们的mTTFMsg中 >_<
5 Z! T2 N% m* K1 z/ n
1 }" i% M: o" E- F, K$ \$ h, x/ F                if(l). u7 F/ v  }/ j! e- q2 |" {6 o

; Q: ^' H: A" x; F( i% Q8 O                        mTTFMsg->point.second = m + ( max_height >> 6 ) + mTTFMsg->char_spacer;# z6 {5 x( W5 ~/ J

# @& [9 e$ r4 H7 E                else # a0 g# s7 x0 X' g5 q& a
& V% Q* Z% l* M( O+ ?/ j1 @
                        mTTFMsg->point.second = m;
2 H0 s  S% C3 d  x' f( e; p8 z
# j( Y0 S; ^7 [, L# q  * A( c# b9 D& |. j3 v. X
9 d# d( t& }3 i3 M4 y  L0 n
                mTTFMsg->point.first = 0;//另起一行
! l! |3 Y8 Z, A/ T. m$ b
' P+ |! b* @" E  
: a9 Q5 v5 X; L, g& Z* l# H0 O$ R! G7 X3 r
                //下面是保存几个最大。
! V% e+ }" f% {" z  i" H
; D8 \; ]8 o2 O  N                mTTFMsg->max.height = max_height >> 6;
0 w6 t, R% J4 A: `- A0 N, |1 S+ g5 w5 ^0 z9 M, |
                mTTFMsg->max.bear=max_bear >> 6;0 ^( D* u8 L: h& _% A9 s0 L
7 o. ]# M5 E) n
                mTTFMsg->max.width=max_width;6 q: Z% i) M$ a+ t1 L8 {( r
8 f9 K1 P8 ^: q  l0 r9 ]" O
  
5 K6 P) p/ [# l( k; Q! K* L0 A6 X7 r# n; `
                mTTFMsg->imgchunk.allocate( tex_side * tex_side * 4,imageData);" c- r* L8 T6 ?, N, q7 }
5 e1 p6 [& `! ^2 ~( T' \5 |
               
6 K; v( [: S+ @5 U" y1 I" g6 L* A) ^& K* d  M2 M
                //不知道为什么要设置img这个中间变量,似乎可以直接从chunk创建贴图
2 `, b" h# y# |( k4 `! _1 C9 a1 R; G2 @3 [
        //--Image img;
& B+ T2 m5 N4 D' N$ _! h1 `& ?% g; S& ~$ S! `' W0 Q
                //img.loadRawData( imgchunk, tex_side, tex_side, PF_A8R8G8B8 );
& K7 Q8 @, H* H- \1 m! ]% m0 o9 |6 @; Y; I2 J( `
  
& a/ S6 {+ o; |$ \7 L4 o; S! c$ J& X/ X+ y
                //贴图名
/ b  y2 b0 r0 L! N/ y
( Y2 D6 n3 V9 X1 n        String texName = mName + "Texture";3 G9 b" }: B" X6 l* ]. R
+ y/ |) e% g; ]* n; i
                // Load texture with no mipmaps 7 c- m: d9 {3 j  \" x

, r8 A1 B! p  Z! ~        // 把从img创建位图改成直接从chunk创建贴图 9 Z. K5 K' Q8 D# x

6 c  P8 d& a  w8 j                //TextureManager::getSingleton().loadImage( texName , img, TEX_TYPE_2D, 0  );" A, }/ L, |# P- H
: I, T: z5 B) N
                TextureManager::getSingleton().loadRawData ( texName , mTTFMsg->imgchunk,tex_side, tex_side,PF_A8R8G8B8, TEX_TYPE_2D, 0  );
( b3 @! Y' B9 A; x" Q0 R
: w% l" @8 g! Y        TextureUnitState* t = mpMaterial->getTechnique(0)->getPass(0)->createTextureUnitState( texName );  _* n4 V2 T: M. [

7 e3 `  U% ]# N' s                // Allow min/mag filter, but no mip
, P0 x) \, G, c0 \
+ m4 R. w, X, w( j) p5 [                t->setTextureFiltering(FO_LINEAR, FO_LINEAR, FO_NONE);
6 v/ x$ p4 U  A1 e1 E* w5 p' M; P+ @  f$ v2 `" v7 K
        // SDDatachunk will delete imageData 1 ], _# g, y1 i/ v7 \. j1 ?
" D4 }* r6 O5 \( T) k9 b$ _5 l" v
        
6 c3 g8 U3 b) z; E5 G7 f3 y% Q; r7 r1 Y
+ }: S% @* L5 K    }
8 L; `. p; M2 \( Q- p+ ^2 ^
/ J/ _! N( u. E        你应该对照一下以前的函数,改了很多的。 4 N7 h; J1 X: c3 I* f$ K
7 @9 T- p1 A* {6 i
  
( j* p  t; Z+ \0 |; c3 x$ R% f5 R3 J8 x* A4 C
  + H0 ^0 a- |' @2 h1 u4 T/ Z% U4 j) K! F0 x, a

4 a; g' m* Y' S+ t, P! Q(3) ( F9 @5 G! ^+ {. ^# Q
  ~3 h: x/ b0 i8 d
        然后最重要的是动态的申请和画字。 2 a+ u9 c0 O, F# K
1 L3 Z1 x# m) h' x9 `* S' m
        首先最重要的是我们要一个方法得到汉字的unicode码,我们用到了unicodeMap数组,提供了区位码到unicode码的转换工作,等一下提供这个表给你,好不容易从网上找到的阿,可惜这个表没有中文标点的对应,如果希望支持中文标点,就要努力找到unicode码并加进这个表了。这个表是这样的 char c[3]="邸";unicodeMap[94*(c[0]-0xa0-1)+c[1]-0xa0-1];就得到邸的unicode码,不知道为什么没有5165~5169的unicode码,是轮空么? 8 i  u. E' X& s$ s6 l& N$ U, r- G
% A/ `9 \2 b- n  t
        
: U  W% P( r2 p1 Z1 \( |# W, W
% G7 F: H' _( b1 Q; E: R; _        申请渲染(字) - O# n$ y4 p1 ^# l6 J) `! e, Y

; B9 c7 Z5 V: e2 q' t% Q# L6 W        {$ e* c( ?* @" G$ R6 F

) [' a4 ?- Z8 {. {0 }$ X                if(有这个字)
* B$ Y8 e7 Z- ]" e$ {1 n( z1 _+ J' Q! F% }+ s- x3 J
                        返回位置
  t: e! R: H1 n$ q1 m2 \7 `4 d. [# X* G  @( \
                else
4 L# q) _3 J' W7 m1 F. h( |9 O$ |% h# Z3 {
                {% j9 v5 u* R7 d1 V  n! j

9 y" L8 J6 l7 d                        if(有空间)& h# V" B8 {" d. L

" U5 Q6 B7 T( O7 R7 {: b                                画字
# U3 y: Z" X- V- ?2 C0 v# v: \& F
# y+ i+ p- }! z1 R/ {) g                        else( n& K: F# h" |) J  w( h7 {

3 W( u6 s- W* H5 |# ^: Y  I# S! I                            找不用的字//找不到就出错,没地方画了
) a" }9 c8 t: Z' Q% s$ y/ N1 J( {
                                删除 在这个位置上画字
! P3 B% L9 J+ K' ?/ Z- u
1 z: t: y! R5 a                返回位置
" t9 h0 I: ]  |+ w% g1 B7 @+ f. u/ g+ |& a' r1 V+ F0 U9 V( v
                }
6 |8 e! V5 Z6 [% g& C9 U) t3 k( a9 P: A. P# e4 b* p
        }
( m1 N7 I6 d( G3 |, r6 R, W7 Y- y" Z3 c  c( V; W0 B$ ^) f
        上面很直观把,大体就这个意思了,申请渲染的函数是inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )  const。去掉const改一改。得到 & {& d3 Z' K; _; C( D3 U7 @
0 j4 Q+ c# c# x, ?  o4 V
        a.申请渲染
' c" F- I0 y7 w* v: L
5 X8 _; U$ t( c        inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )         
' P2 F% D6 M$ {  U9 [+ I: Q
; g3 _* J* f5 M, @0 e        {. c; S1 L' J. [
3 U# A3 g8 x& z! n, u2 ~' M7 i
                unsigned long idx = OGRE_GLYPH_INDEX(id);/ I+ w) y  w3 H: Z# ^

" H" |' j6 Y7 y  r+ R; q3 m- r7 ?                if(this->mType==FT_TRUETYPE)//ttf?
: {5 C' f* W4 y9 l( @2 \$ p1 a" }, B0 t+ M* q7 o- E
                if(id>=161&&idx<OGRE_NUM_GLYPHS)//汉字?7 W6 _7 {. e- c+ o0 X
! @. M# S) _: J' h# n* {2 g& r7 f
                        if(!mTexCoords_v2[ idx ])//没有?6 d$ F! _, N3 n0 s# J
6 K# V6 ^+ o+ {3 F2 W
                                setChar(id);//画字去 4 Z+ I7 r3 ^) k2 A; e2 s8 S

2 m; m9 Q  I4 o, H9 M; I! E            
' ?- R+ s. `) g/ y' ~8 g$ |; C
0 N, _$ K% i" I; J+ y, T            u1 = mTexCoords_u1[ idx ];; W$ o% v9 [6 N6 s
  |4 g8 o; T: c5 _+ X
            v1 = mTexCoords_v1[ idx ];; y9 p& K8 p% a+ @  X+ P, ?

( M9 I( s) x: I7 p2 i, O            u2 = mTexCoords_u2[ idx ];
2 N0 U% j$ T# t1 ~
. }5 g6 `) B3 C: B: I5 {" l3 n0 Q            v2 = mTexCoords_v2[ idx ];
. a/ l: l& [% o4 n) \! A7 V+ W; ~1 _8 ?& |
        }
& v: j" Z; a# X- |$ g$ u
: b! {3 n  I+ T5 m( s# u: q        b.画字等
  J  ?1 p' S; E) M: o8 ~; {/ s8 H6 y/ \
5 l0 O. O2 |, w" g        bool Font::setChar(unsigned long dwChar)$ n5 v. K- }. O. ?9 D3 F: f/ g. a

. @1 C9 r- R. @8 T( @        {
- ^- }* k4 G( a+ @3 }" {  L# m  ]/ \
                int j,k;
) o7 j& V; Q% C' N* k3 s* k" t6 l! w; a9 G8 }5 o! C1 @+ f! {- Y: C
                uchar* pDest;//操作数据的指针 5 l8 w0 V6 u. J" _

: t3 M0 G: V1 B5 C' i" \* m- X' O                mProportion=0.8;//不知为什么,总觉得中文都太扁平了,所以设置这个参数,在《让OGRE支持中文》中创造的参数 . @% c, o: U8 S* }- j
! O3 D! e' X% O/ ]+ I5 c) Y3 A
                Image::Rect  rect;//画字的位置
, y5 Z3 ]- x4 X0 |' a2 b
; [0 Q1 D( e7 E4 T/ n0 B                if(!mTTFMsg->getRect(rect)/*回头看看这个函数吧*/)//如果得不到空位置 6 n  X  ?* j- u! ^: V
+ c1 a. E# r" S8 _
                {3 u  |  X* G8 S. N8 b' r

! n' Y; {8 q; j" N8 R                        for(int i=161;i<OGRE_NUM_GLYPHS;++i)//寻找不用的字 & V2 M( y& [* ^1 |( T+ q
. ~* \4 I+ e/ \7 K
                        {) y2 }0 k9 }3 R  L- p9 ^

5 Z' j1 W, L5 g$ L+ [% A8 ?                                if(!mUsing&&mTexCoords_v2)
) K8 G5 j% _! u% @( S5 Y. K5 T3 W% n* i- Z+ u4 \9 M% s
                                {
6 \, k1 M5 J/ ~% b* j! {3 h2 d. F- g1 O
                                        // 得到坐标
# i' S0 A2 p5 ]9 p
* }* O9 Q- a% @6 \$ L/ t                                        rect.left=mTexCoords_u1*512;
& q) }! _* o$ Q1 j+ j! t
" c, d/ ]6 q% Y+ l                                        rect.top=mTexCoords_v1*512;
3 ^8 Y9 W3 e, p# G5 G$ Q2 T+ X! K& T* q; [/ F  n
                                        rect.bottom=mTTFMsg->max.height;
# Y+ I  E$ Q$ v* n5 J4 F/ y! {% V: W
                                        rect.right=mTTFMsg->max.width;
2 n: A3 F$ G/ y: n; ?4 p* }1 N2 J" Z9 W' k4 t2 T5 A
  3 t6 ^% s# P% B- i; _1 ]3 D: [( H

( u" K! |7 p& Q8 k                                        2 {/ O$ b. ^  K5 d

6 o* d( g( h3 L6 x" I" ^* L                                       
& P  T! k3 o" t+ l- v/ {
2 U; D; m# p; i* M                                * n4 G- N: d" E' p, o7 A4 m6 F" `. L

. T8 I& \* ]. I/ {) a9 l0 {) ?                                        //擦除(这段代码没有试验过,等做完输入的类在检查吧) / A" ~+ X5 u6 \

. j5 m. z6 B" n                                        for( j = 0; j < mTTFMsg->max.height; j++ )3 N$ B; Y" ~6 \" u. T( X& b  l
* W& A3 w3 _% f: T
                                        {+ O1 a& }2 |. X0 p
* A6 @& A$ n4 d
                                                pDest=mTTFMsg->imgchunk.getPtr();
( }7 l  j+ E) O6 _* O
7 h+ H1 x8 d: V5 f                                                pDest+=((j + rect.top)* (512*4)) + rect.left * 4;, r( v2 l& t5 k% q  F/ I

" ]( H9 W4 h" m  C5 Q. I/ Z; O$ H                                                memset(pDest,0,mTTFMsg->max.width*4);! |' ?; w3 f/ l: m* {6 O
  p- Y: m) N8 ~2 s
                                        }
2 E) k8 M( F. Q
1 F, x% z! n1 L/ Z                                        mTexCoords_u1=mTexCoords_v1=mTexCoords_u2=mTexCoords_v2=0;, G' B1 d3 y' K0 z# k- T/ ]
4 T2 K/ N8 @4 v5 k
  
( D) a1 ~* ?/ R: V9 ~! }5 p, e
! ?# Y7 w$ ?8 o5 P                                        break;! ~# _/ N& f! ^- i* c, j2 A/ g9 e

: `0 F4 K- }- v( v                                }
! P0 ], u7 Z0 {( x" v. O! Q# d! Q5 G2 v3 p
                        }
9 c8 C( k5 L7 W( w+ n$ {# T* S& ?% Y2 T; f: p; q) s
                        3 }; A" F$ r) i3 }0 U8 p: u

* K0 W% \: h: ~7 b                        if(rect.top==-1)//啊啊啊啊啊啊啊啊啊,贴图竟然都用完了,没办法了,出错了 / U4 O) F4 \$ a

- E7 G. S- {0 z3 V- I, ]                        {6 q6 f; {9 u' h* w! p6 O: S# E
' e: b, F. O  s! }
                                LogManager::getSingleton().logMessage("你太贪婪了,用的汉字太多了,这是对你的惩罚."); + S9 X  A7 E( [3 N* I$ U0 d

9 r2 a0 s% l, |2 {+ y' ^                                return false;
& o. X0 Y; G* `0 v- M' B* s+ W% r1 s5 f5 D1 q! f( `# y2 E6 ^3 c2 V
                        }
8 U! Q. R/ R# q5 K% O9 @, ~/ g& h3 ~0 z1 ?6 e' p8 W
        
, W0 E" _4 n5 q
- t0 ?1 Y+ }" T                }* D) ~" V6 Z+ Q6 H! N' w; r
# L' c  _. F7 S/ E3 X
                        + V" l6 V- A, @4 k# H4 @
8 Q# \$ {2 W/ f- ?2 Y
                6 n, R- x7 E: i. G1 h; \# ]
* {$ S+ E. Q0 X: O3 S
                  //以下画字的都是招葫芦画瓢的, ! b3 }+ g3 k# ?; [1 C: W: }
# m5 C0 d! i; f9 V5 K
                  FILE *fo_def = stdout;$ P" p0 ]. p# o
2 q+ R& \- F7 S
                 FT_Error ftResult;2 S& ~# G$ J% I; j; C5 |
' Z: Z% w) J/ F
  
, F3 t  ?' I& O" l5 |
& l6 H4 R" g+ R, F) ?" l/ k            // Load & render glyph
3 }0 V# k4 x' F5 r9 }+ W3 w1 G; M# u1 W
                  : G2 H3 ~3 n6 k0 G0 z: }9 Q- Y

# K; @% J- B# y$ c$ i            ftResult = FT_Load_Char( mTTFMsg->face, unicodeMap[dwChar-161], FT_LOAD_RENDER );//读取字体
+ m+ P! ^5 }1 |8 y4 o
' I6 q2 l8 N5 A+ x            if (ftResult)- B/ M) q* h( u) K' i; x9 Q

9 r6 S7 ]* v8 c& t7 x; E            {
! ?, o; c* @, ^" s5 w, T0 h
* H+ i: h1 q+ O                // problem loading this glyph, continue 4 u- y1 ^5 V9 @% ]- Z+ {/ D

  }* X: h; |' a6 m5 j. P- l                LogManager::getSingleton().logMessage("Info: cannot load character " +
' ?, |' O% f! d( p' h) F& {
* H; U4 l& I- r( P6 |  H                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);
! q' \6 ^8 N1 G# U* Z4 |' ~
: A3 F4 ~9 |4 p$ P; L/ ^5 R+ r                return false;//如果错误跳过 8 [5 r) `, G8 C  o& p; m

8 y* Z# g; o3 Q) {' S            }: B  C5 d  ?1 s

0 t! c0 t/ f- p& Z! i2 o2 N! i1 u  5 A' L' Z$ C, q1 ?$ i% ^: v% H
4 _" U0 Q. ]+ C. a5 W! b
          unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;7 E; E7 h0 L. A8 w% Z
. R8 r8 B% c' m% o% ]6 ?
                  // 位图指针
; K3 ~8 F6 L9 I. b7 \9 b$ P2 s) {* b# z: Z; C: a& j
            if (!buffer)
1 g' w9 f: \8 v7 [5 x% W* P0 w, T/ y3 A2 }
            {
, O5 W4 ]5 s) _. P" d
9 _! G( Q3 x$ U: m5 n* M' s                // Yuck, FT didn't detect this but generated a null pointer!
# F& Z* x3 x! Q: }
. `+ ~6 ^- N. F  R0 A                LogManager::getSingleton().logMessage("Info: 1111Freetype returned null for character " +9 @2 K9 `# |; b2 j7 i

0 I  W& b9 z" b                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);
  b* U2 T2 G4 \# d) @8 b7 t, i$ B) Y+ z% E. r; l4 ?
                return false;//如果得不到跳过 # z. A! {+ L. U: C

: D4 v* J* @1 i            }
/ E, I8 q. U  r- M3 {( H/ K  q. P  ]' s0 c$ ?' x' n: F2 r0 S
  , ]3 T: O9 T, N9 g9 u
3 O* o. e8 z' P  N
                         int y_bearnig = ( mTTFMsg->max.bear) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );
/ A) u8 O8 a/ t7 n+ ?
& ^& Z9 G" s/ N8 W       " V% Q! P6 d9 H9 q; ^; v
6 i) w7 m/ u* D& j% W. F3 Y
                        
. y# {5 h. G+ ^
2 N+ q* t9 i1 d( m4 S& \: \            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )+ o7 ?2 ^, ]+ d

; ?2 Y; o) H) {6 a' w" {' e4 u            {6 f% }1 T4 v* ^# U7 ?

1 d: ^: I$ G, s0 d9 r" d                int row = j + rect.top+y_bearnig;: m' G. V5 q; Z. N3 t; E" q4 m
/ y& b$ L* T9 t" g
                int col = rect.left;//列
( y: v, t7 [4 _/ @1 S  d. a
$ b. c" |. T% T2 V                                pDest=mTTFMsg->imgchunk.getPtr();: b* \% v2 }& Y; p/ O

" }% F% p+ Q/ e8 b' V  r3 p; F  2 z1 [: Q6 V  R) m" Y9 r0 `( A
* N6 a/ `2 S2 Y( R3 J- X) p% a
                        
7 T. Y( v1 q' m
& u7 e; K. |0 G* L6 W; u5 Y                                pDest+=(row * (512*4)) + col * 4;
) C! S/ G) P+ I( A+ [! Z1 Z5 h' J
               for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//每行的点 1 y: l; ?: q! V4 c, a! r1 s6 I
/ E  A* O/ C6 Q0 N
                {! U5 V0 C0 L( n
7 F% _& f. w7 s5 G
                    if (mAntialiasColour): J4 @& F9 R( l& E8 t5 a
/ [  d/ J1 t8 _$ l
                    {
, ^3 b# U+ T5 k$ |5 J$ n& }
  e0 u! d2 e# c7 t" ^, Y                        // Use the same greyscale pixel for all components RGBA
/ F1 O6 w4 l' x: H! k1 s7 Y  C. y* U* ^2 P8 |0 P
                                                        *pDest++= *buffer;
# e1 [# P- N9 j! @& t0 u
+ s7 X* Q7 L( N9 Z/ v% |6 b                            *pDest++= *buffer;! b; g* E- F1 ]. U( |, [; M

+ N0 j/ m3 u7 ~0 S1 E/ ~9 S                            *pDest++= *buffer;9 S0 s0 u& _; V8 J- A: }) j- F
; O3 a! K. n' y2 m% P
                    }
7 I5 N; ]: Q  @0 h, S5 q' _6 w# H$ a7 r) C
                    else ; n( f9 Z* {, U: y$ y
. V8 f- L* U1 q+ r, d7 t( g
                    {
9 Q5 O  \" {* m2 W8 a
: I2 d8 \) f: Q" B                        // Clamp colour to full white or off
: o% X# Y. A' @( X/ K+ O/ a( P
& O1 r6 F" {* C( T                        if (*buffer > 0). G! t6 x) X1 }$ W- C4 Z) n  O# V' `

9 z/ M& m# P& F9 I7 `7 x/ b6 Z% o                        {
4 V. W2 o7 V4 z( C; d+ J, G7 E
4 Q* _: J, U: g                            *pDest++= 0xFF;& w) r' ]& N) h: d+ S
  _) x  ?1 m& Q! \/ f; _
                            *pDest++= 0xFF;
: a( {: |' ^- a7 |6 M0 o0 z
+ C% }8 Q4 p$ i$ D+ f/ R                            *pDest++= 0xFF;* j- g  K) T( `. e/ {: G+ v
6 y: i+ R% e6 j
                        }
  U3 S# F1 ^* k& P# m8 L3 O/ C: ?- G5 F4 L
                        else
' J2 q4 q' n5 G& l
. ~7 ]" N& T  L# |+ H                        {
- h" V* `! V4 {+ p# @( L+ `
& Y8 A: Z6 J4 c  ?* p* {, n2 r2 k                            *pDest++= 0;) z3 z: c' D3 h( T. D

- }% \% I" u7 u% q# V                            *pDest++= 0;) B) s$ f4 V1 _) m+ u
- |& `9 N! T5 Y$ |' @2 Y/ g
                            *pDest++= 0;
( p3 O$ O) B  B6 o/ D, ?: P; Y! [4 ]) s  h( I) s
                        }
0 y& _/ o% e0 `" F
2 e: K6 \" _) O8 u) e/ _" Y                    }
* V0 Q5 Z, F  ?
( p$ K  f7 i+ x: b; r2 F                    // Always use the greyscale value for alpha
0 s+ k$ W, p2 W* i+ Q, g+ T# Z, G- \% F# `" N
                                          I5 |% J# c9 s0 t4 b
. n; C7 t2 o# s: n" R- `3 Q' w; U
                                //      LogManager::getSingleton().logMessage(StringConverter::toString(*buffer)+"is cool");6 \: R* K4 u/ B; _/ C- i

( Z' ?) l- y8 Z' ~' j* \                    *pDest++= *buffer++;2 U6 c) J5 J. E+ [% t

7 {/ W% T2 l. b) [) j4 i                }2 G3 |) _1 \/ A! [4 ^$ a
  r, n- n9 O4 _0 W
                                  r; |7 k6 C  M: B5 [
- W) Q( D6 ~+ E# I$ |
                        }! M; x# m5 H  m; ]
. L4 _+ u4 ~  t
                        // 设置位置 + C  o# s% g, o- q" e& f

$ B; ~9 _5 n; L$ q1 Q                        this->setGlyphTexCoords( dwChar,
! l, A6 l9 J' y- W# f. Y! Q/ l+ X/ z: O' S9 W4 @3 H  B2 z& M8 C2 n
                                 (Real)rect.left / 512.0f,  // u1
# x1 j+ i2 o/ y5 I$ A7 y+ J1 ~+ X8 D" @! B7 e- |6 P
                                (Real)rect.top / 512.0f,  // v1
; ]1 d+ q0 U& i3 q7 \) l# n/ r0 o2 z6 q8 `* V# Y8 ~' e2 z
                                (Real)( rect.left + (mTTFMsg->face->glyph->advance.x >> 6) ) / 512.0f, // u29 Q4 t  a0 h- \+ l8 n3 q

) o4 l& q, p6 E6 U5 ^                                (Real)( rect.top + rect.bottom ) / 512.0f // v2
* ^5 z, g) m0 H# r; R
$ C  r+ R; G& h% }4 ]. b                                        );1 ^& a* a7 i/ A5 T+ a
" T2 W- f, c3 Y+ F
                mTTFMsg->dirty=true;//贴图需要更新
2 a3 ?1 G0 X& s
5 `+ {. c2 U; S& v( q                return true;1 c! D  T. a: C0 D" i
* I3 T( S& N+ v: E  P( i5 U
        }1 w! Y" v+ c. }3 Z' x8 z

2 Y' K$ u: \" n: T! X5 g  
, |3 `+ y9 }, D% D  T& z; y: D1 S- m' O* s5 |1 ?% J1 a
(4) / g. J  E9 f& l. v
7 l7 d! G8 ]0 `# q; Q. O9 L
        松口气吧,繁重的工作都做完了,就是更新贴图了。 3 d- V& h6 K6 ~

$ {1 f( F4 S! ^8 F+ a8 M/ D  e        Font类中~
2 K" A1 J- _1 b, E  ?$ R& U; N0 l
        inline void write()
% ~5 ^, x2 G  `; t  V0 L
' B$ Q2 a% D( N/ d0 l  |* x                {
) t8 R8 H- g" G* S$ W9 }8 W0 N8 u2 t& ~0 o/ M4 c' S" Q& S
                        if(mTTFMsg->dirty)
; u) T- X  I) [9 M" ]6 U! D7 S' {  s
* |0 x. [8 w$ c! o+ h. A- B                        {      
0 A5 m! `9 @0 x, P/ m. _9 H9 V4 l* y1 u2 ^6 R7 ~$ ~6 V
                                // 重新载入贴图,顺便说一句,类似功能的函数还有
% I6 w, J  Q/ Q8 b5 O5 I( ~
: q* f% M, |; x2 C- z                                //virtual void  blitToTexture (const Image &src, unsigned uStartX, unsigned uStartY)=0 . \" T3 ]- X, a

' u8 t8 h* ?" h  \  ], G                                //和virtual void  blitImage (const Image &src, const Image::Rect imgRect, const Image::Rect texRect)6 g2 g( r' C. L" O- e
3 Y+ V" u. I! u+ t0 `$ @* a- R" n5 m
                                //不过blitToTexture()在ogre-win32-v0-14-0之前没有实现,没有尝试使用。 blitImage()就算到现在也没有实现。 ; p; i8 _2 P# n2 c9 V

, H, c$ C# j  |/ F- U0 G( h  # h9 I6 \  j- y5 {8 c4 [
& T" R3 K/ |5 U: T
                                TextureManager::getSingleton().unload ( mName + "Texture");7 N8 R' \  ]* N9 ^; U3 `/ o( \

; ]6 V4 Z' R1 `. l$ s4 ~                                TextureManager::getSingleton().loadRawData ( mName + "Texture" , mTTFMsg->imgchunk,512, 512,PF_A8R8G8B8, TEX_TYPE_2D, 0  );  g9 ]7 i7 n  g5 f) U( o
) B8 b: T( z$ H- g& s# s2 `
                                mTTFMsg->dirty=false;
" @( W5 w( x, i
8 p  u; V0 k: Z                        }, t& r% `4 p: ^) V( M

; C. i+ f+ q/ |# M9 c4 y7 f                }
; u: k* \8 U) \3 G
0 u2 p9 Z2 x: N& r0 C' y  & c$ U8 p0 D0 L# N& R

* n% D7 T- @8 H* ~4 @/ ]         在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。
  g) P: s- s9 ~) ^6 m
: Q% \+ D* [; S) g  , l. Z8 T5 x& d' n: v+ B
. g* N: }' `2 x6 g5 s6 D. O
  % A( ^4 |% B  G6 x6 z0 x# j$ Q

  O1 g2 C- d5 B+ T7 E+ e4.结果。 ' T' o& X, C8 \( X' |
& v3 c; U/ d$ t% \4 a
        好长阿,写了好长。虽然多是代码,但写注释也很累啊。重温了这些天的工作结果。就像上一篇一样“在OpenGL和DX9.0中成功的支持了中文,但是DX7.0中竟然出现了运行错误,具体问题还不清楚,还望各位高手指教。”。不过本来OGRE就不怎么支持DX7的,不管了吧。OpenGL中渲染的比DX9.0清晰,是我的显卡的原因么?以上的winXp+vs2003.net+艾尔沙980se通过~。。
' Q! t  r$ A8 F* y, W9 k2 M9 P/ A1 q9 ]+ w7 N' v
        顺便说两句,上次发表了拙作,没想到好多朋友和高人们找到了我。甚至联系到了一个南方的公司,说要做一个引擎支持中文的方面。但是卖完400多的火车票之后竟然因为住房问题作废了,5555,退票少了80元啊。还是自己差阿,如果再多学点可能就能要我了把~。努力吧,争取写《让OGRE支持中文》三部曲。 0 Y$ Z" K9 F; O+ S8 }8 l9 p

  G' [+ |/ u  P        下一篇应该是《可以输入中文了》。 5 V2 E- b2 N1 O
  H8 [( z5 t8 V3 q6 h6 f
        也可能写不出来的~~~~~~~~~~~~~~~~~~~~    % `! q* x) Y3 `- @: W4 G( D# b" E

- M) u' R" {% S& I3 Y4 V    相关文件 % }' m! y1 L* z, b2 ]
; i( }5 j" l; N2 h
    chinese.fontdef//字体信息文件 放在资源文件加中 6 D0 `8 K, Z  L, B3 V
' x8 d. k" l9 B
    font.png//字体图片 放在资源文件加中 3 a4 y3 ~( a  M5 i, p" T* x
, r/ k0 D& Z. R! i! w
  
. a! V! q, I' R+ F( Y$ |# T' f% I7 E
$ r: ~' I% y! ]+ r7 A    OgreFont.cpp) [0 x# e4 p2 {3 @4 o8 u  b
( |% W4 i  R" x% l/ n
    OgreFont.h
. _& G; ]+ i2 c0 R/ _( x2 s- L" \! L, ?7 M4 m
    OgreFontManager.cpp
, s* [1 i+ G( {$ w) N( U- h8 `2 ~3 N: l
    OgreTextAreaGuiElement.cpp/ D) E- J; ]" y# ~

1 M6 ?9 v% H& \, v" M    //上面文件覆盖同名文件 就可以 先备份 2 ?$ E$ n$ `+ X9 @8 u

5 `5 T1 C9 M; Q3 V2 J   1 J9 `7 G7 J* f% t

& Y1 w# \+ P+ ?3 L8 k0 P( N   solo5.ttf//这个是一个中文ttf 我直接替换了原来的ttf
" R0 D2 k* T: Q- m! }
1 c  \3 m6 @9 T  a   unicodemap.h//这个重要,是换算unicode码的数组(文中提到) # q2 w! @3 d0 v, C7 M. F
: c2 P( O8 ~* s, C/ E4 p
  ; Q9 o4 D/ p0 F, t2 t4 |

6 h* o0 j" f! B+ {0 e这个是在ogre-win32-v0-14-0基础上改的(上次是ogre-win32-v0-13-1), + ~; d! i% u9 e' V: ^
, ?  B' @8 d4 d
请到http://sourceforge.net/projects/ogre/下载 , r# l) b3 `' B+ o! L
& j& z7 Y/ h  w4 o8 M0 R0 _- E- x
配套档案下载:http://www.gameres.com/Articles/ ... /ttf.files/file.rar
+ \! F/ T2 a4 a! I" n/ j: f; Z
0 S- M  d: ^9 v/ i 免费打工仔QQ:1850070
6 T( F6 z& f1 t/ n3 B# ?: a8 i  t' h
From: GameRes
  r& d) R8 }8 s$ F( |5 I/ z/ y6 ?' }7 k
http://www.gameres.com
/ q3 o, l; H) K2 c! Q" }) C. R
# V8 l: k9 ?( j$ x" X上面图中“免费打工仔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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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