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

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

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

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

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

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

开源的图形渲染引擎OGRE(3) --让OGRE支持中文TTF字体
! D# z- _" L  a, ?: f% d) C
( d- H4 x; i6 ^' g2 W7 ?0.还是前言
  Z. g) C+ X+ E, X$ w2 j) U6 i" n* ?! T! R
        如果你希望能看懂这篇文章,请先确定你已经看到了《让OGRE支持中文》(http://www.gameres.com/Articles/Program/Visual/3D/OgreSupChn.htm),因为本文是在上一篇文章的基础上写的,并且假设文件都已经按照上一篇文章进行了手术。但是如果你只想简单的使用TTF字体,只要下载本文附带的文件,重新编译就可以了。
3 I* I& ?9 C7 f( k8 \* s$ _0 ?2 ?) n& \+ q' j& N
1.检讨
8 r8 [( t0 j( Y2 V9 G1 \7 w1 i5 R. F/ X! S  w3 ?
        正如上回说的,我们已经实现了一个位图的字体。但是当冷静下来思考时,就能发现这种方法的诸多缺陷。读入一个2048*2048的位图,等于在显存中保存一个2048*2048的贴图,不说是否所有显卡都支持这么大的贴图,单是每个Font字体类吃显存的胃口,就足以令人心惊肉跳。如果定义足够多的字体类,我想你的游戏的配置要求,在某些方面足以超过《DOOM3》了。
) I# b! A" k# z9 ]
: q/ N& ~. f, S! p        而且这并不是唯一的缺陷,文字大小相对于位图大小比例相差太大,导致浮点数的文字位置误差很大,你可以在一个文字旁边看到其他文字的影子。(虽然可以通过增加文字间距来解决。)还有点阵字体本身的缺陷,就是字形单一,不适合放大缩小,一些文字边缘的马赛克,足以熄灭任何玩家的投入感。
/ R6 Q$ S# s& Q
! x( q) k( d: ]' w  m: b' i' F) D        似乎TTF是唯一的解决之道。 5 ]9 @7 ~) G/ L" ?

3 [' O+ \) u. Z1 j2.基本知识
- B; r. v" i, x$ S& e9 |( F* U2 D) N  J0 i0 g
(1)TTF字体。
# P  a( Y: |5 p; [& k& ^. Q; l1 P& U& m( D
        TTF是一种矢量字库。我们经常可以听到矢量这个词,像是FLASH中的矢量图形,在100*100分辨率下制作的flash,就算它放大为全屏,显示出的画面也不会出现马赛克。所谓矢量,其实说白了就是用点和线来描述图形,这样,在图形需要放大的时候,只要把所有这个图形的点和线放大相应的倍数就可以了。而且,在网站上有很多的TTF字库可以下载,或者你可以去买一些专门的字库光盘。然后在你发行你精心制作的游戏时,可以顺便捎上这些后缀为.ttf的文件就行了。包括Quake这样的惊世之作,也都是用的TTF字库。
1 w4 Z8 \1 H% h' n, G1 L! l) t: Z6 I* D
2 J+ v% h0 E& Z$ i( ^(2)FreeType2库 ! [' u8 w. |  B. d8 d" s" G
6 s: P. `/ C0 P# J6 @8 e8 a
        在http://www.freetype.org,有一个FreeType的免费库,而且是OpenSource的。它目前有2个版本:1.0和2.0。其区别在于,1.0只能读取TTF格式的,而2.0支持更多的文件格式,在使用它之前请详细阅读所要遵循的Licence,以下是摘自FreeType2.0对字库的支持列表: $ x' W, g, j) V/ ~9 [# R

7 o3 Z1 l* \2 M0 [, G) _# _        TrueType fonts (and collections) ' R$ H( w! Z; l; M3 r/ ]/ X0 R

" k& D. r2 K' I1 o0 l        Type 1 fonts , A5 g+ n% F" }

0 U  C( k/ F2 N! ?2 H7 A! }        CID-keyed Type 1 fonts
, s! }5 H& g( D8 u( e) J
* I& s9 D7 o5 H2 k2 n        CFF fonts " D) o; j. w! f

/ a/ [  w5 H, e$ K; p        OpenType fonts (both TrueType and CFF variants) 6 e; `) v: }. ]) l; G

$ O1 s* w6 u4 I1 {% \        SFNT-based bitmap fonts 7 f# x  `; y. b( C# c$ X9 z

; G' Q6 W& s" e: Y& u" i        X11 PCF fonts
  ~- r7 z' S' v+ k" A; B" I8 o: a: [7 S9 e
        Windows FNT fonts + ]1 \7 _: C% F5 E3 h* ^

0 B% D) F: H( P(3)“主体思想”
: ^* N  s1 q2 s, f' C6 X+ f+ C" k$ ]8 O, P2 P
        请参照炎龙工作室的《游戏中汉字显示的实现与技巧》这篇文章,可惜使用的是Windows API,作者千里马肝,上网上搜一下吧。 ! G$ D  n# M' U: N$ v7 h" p

% I0 T, X: j4 i; E# ^        附带说一句,上面两条都是直接从这文章中剪切下来的,>_<  不要骂我啊,不知道算不算侵权呢。 * }; m6 S$ x. M* c
+ W7 e/ V% h' _# v0 A5 Y& B
3.动手术---比你想象的要麻烦 , V9 \+ `4 X8 m3 A6 M
(1) 6 \+ |1 u$ j) c7 p
        首先要告诉字体类,我们下一次渲染需要哪些字。以便字体类可以在需要的时候释放不使用的字体。 4 n; z2 ^, c8 o

& p1 B. ^( g  J$ H7 @3 t+ j        在Font类中~ 9 R0 B$ P+ C! {+ ]8 G' b

. G' L0 C5 E# `9 n$ z1 C0 l        a.增加数据 bool mUsing[OGRE_NUM_GLYPHS]; 用来标记文字是否使用。
3 v! `/ G4 F  J9 d: I# M
6 S9 Z1 A# w1 b" E$ o6 t' O5 p: ~8 s        b.增加函数 ) }$ _: G% f7 K: ^, \  i; z5 N

1 d6 I+ q3 @- A; ~. k/ {                inline void setUsing(std::vector<unsigned long>& caption)$ F* ^! w3 V' Q7 c  [
3 b. @' z; V9 e6 C
                {+ m8 V; t0 u: N5 f. k

9 x1 s( K6 ^) f3 i/ a( @4 H                        memset(this->mUsing,0,sizeof(this->mUsing));4 G$ k( F9 d  d' T+ A

' b* C3 `/ V/ y: g+ a                        std::vector<unsigned long>::iterator it;4 B+ g/ b9 O+ p+ }

" c+ \% w( R/ S! a                        for(it=caption.begin();it!=caption.end();++it)
0 v9 d* Q6 h7 ?$ J# W. t6 Y! t, Y( e4 F+ K( _* G
                        {
$ N. G* l# A& W8 ?
6 i4 D8 s0 q, `% w& g- X- z                                if(OGRE_GLYPH_INDEX(*it)<OGRE_NUM_GLYPHS)
' g0 C; r5 ?1 Y3 B" r/ G2 ~. O- f' M0 t7 o. w3 f' W# x+ h* Q9 o
                                this->mUsing[OGRE_GLYPH_INDEX(*it)]=1;//标记文字为使用 . G7 w, k- n( g- K8 l6 K. G

1 h' w! Y. z0 o1 c9 E% d1 ]/ R8 j                        }- D5 |3 }1 q+ W; M1 u0 }' u& s  Q9 i
6 Y' X% @* E  F6 _5 `" q
                }1 ?) f' T( y1 [; t
+ S4 z$ m0 |) P- {
        并在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。 2 L" ]: _2 e7 \2 S  z% l
(2)
2 _. ~7 D. m. l) j1 b* ~2 \' Z9 K" M- h/ F6 k6 r, i0 N7 p  C
        然后是修改void Font::createTextureFromFont(void);
  z" e1 Y! s- j- h0 {+ K, @$ {8 I1 J% J$ P0 S6 A4 q
        Font类是通过void Font::createTextureFromFont(void)来把通过FreeType2分析好的英文字画在一个2^n*2^n的贴图上,然后再保存英文字的位置。
. N* {1 g9 _1 j
" v% \' t5 h8 b* u        我们需要修改的是: 6 z  l4 Z) G  m( y0 a
" h; a( {' P7 h0 E+ [. n# F
        a.从函数中分离并保存画字的FreeType2和辅助变量。我们通过一个类来保存和处理这些变量。   u" N) X- e; z. \4 }# L
9 L3 b1 q  B; _1 Q
        class TTFMsg
6 d  l3 z$ H# M" {( R2 I4 r2 a; q
                {) F3 v6 v7 N$ s4 ?! R

$ k) X5 e. I0 z( Y9 w, p$ f8 g                        class Max//类中类,用来保存几个"最大",( M& x* H, t0 T4 d1 E' |9 E

8 M" {6 [- y" L: Q: a                        {
" j6 r3 ~" A* U; L$ R3 p9 ~
+ I& K' k7 H7 u9 X. j& \                                int nothing;//这个是用来占位的,没意义,反正没他就运行出错,可能和数据对齐有关吧。
$ p" ^. J8 D3 U# B# K* D( `5 @1 h7 K4 A+ H4 v4 J
                        public:, r2 E3 l1 w, j3 s# f& M4 Z
                                int height;//文字最大高度 9 A4 A: c4 b8 C- l+ h( K
                                int width;//最大宽度
" T7 h) W9 P; u/ h9 U1 B( Y4 |- }                                int bear;//最大空隙?
- N0 ~; _# s, M  N                        };( Y# B5 Z. ]% F0 F- ?
                public:
& }( S) W3 j4 l: b                        FT_Library ftLibrary;//FreeType2用 * c  H1 p$ C1 B- d  A+ H
                        FT_Face face;//FreeType2接口? 6 c5 ?# ?6 n7 _, f9 \) v9 j
                        uint char_spacer;//文字空隙
: A9 P  W1 n9 W* |$ _, ]                        SDDataChunk ttfchunk;//数据块,用来保存ttf信息 7 ?( Q- E$ I% o! s. ~3 `
                        FT_F26Dot6 ftSize;//FreeType2字体大小 5 h" p5 e# G& z2 k
                        std::pair<uint,uint> point;//在位图上画字的点 , \# q3 S' N; p" n3 f5 e1 K) U) [
                        SDDataChunk imgchunk;//数据块,用来保存位图信息
4 @3 z3 m$ x/ P. n                        bool dirty;//标记,看是否需要更新贴图
' Q& Q' [' p1 u3 P$ e                        Max max;//几个最大
" t6 d! @( w* `+ Q& ^- L
3 c& T  y8 X* H0 D0 \, C/ C1 }                        inline bool init(Font*  font) //这个是初始化函数在void Font::createTextureFromFont(void);中调用.( O, X  z3 W8 G9 H+ y: ]1 w5 F

4 [6 U' s1 z- L' K                        {       ' B) F% T# i  D4 J# e7 t" X& }4 j- y
9 v. J+ y9 H, P/ t6 q
                                //以下都是初始化,大部分都是从void Font::createTextureFromFont(void);移植过来的
6 f  _3 z. B. ]7 `) z3 `0 r8 R. X% o" K7 C
                                dirty=false;
. d6 L# t- t5 N* T  [# q6 o6 e( s" K' j4 p7 [
                                if( FT_Init_FreeType( &ftLibrary ) )
' s8 p- _; {) n4 D
$ R2 E5 U8 L. m/ G9 Y7 D; K                                  Except( Exception::ERR_INTERNAL_ERROR, "Could not init FreeType library!",
9 }2 ?# U% Q; h$ }
& `4 Z6 S* x& ~' m& G0 e" m                                "Font::Font");
7 \& M1 G6 a1 h( @3 w$ ^
' d7 }% {5 V7 V& o+ [               
! j7 P6 U: I. l- Q+ v0 a4 C0 `7 m! B+ P) D7 l  x2 `$ G
                                char_spacer= 5;
' I. Y! i# L+ ?2 G. U; s
/ ?2 W5 ~1 G1 r* y. Q                                FontManager::getSingleton()._findResourceData(font->mSource,ttfchunk);( I: `6 \2 y1 s

; Z) q3 Z  n; a5 f3 T                                if( FT_New_Memory_Face( ftLibrary, ttfchunk.getPtr(), (FT_Long)ttfchunk.getSize() , 0, &face ) )
, s8 }  B! D7 ]+ w+ C0 v
8 N# g: h0 J0 P# U% P$ A* U                                         Except( Exception::ERR_INTERNAL_ERROR,
& d8 A+ y1 G- {, @# g+ ^( ~- r. c
                                        "Could not open font face!", "Font::createTextureFromFont" );! E$ j, @6 c9 V# Q. ?7 J9 E4 O
5 b3 ?% q/ {) B2 s
                                ftSize = (FT_F26Dot6)(font->mTtfSize * (1 << 6));. _+ d: V- {2 f/ n( X

: M3 Z0 F; F( g* l4 i+ I. k                                if( FT_Set_Char_Size( face, ftSize, 0, font->mTtfResolution, 0 ) )' x& i0 g" ?% c# }( \) H: m

% n! y) |! E% G' S* J( X" K                                        Except( Exception::ERR_INTERNAL_ERROR, 6 W1 }# T& `6 z# K* Y; T

# I* P9 F& U/ |% E% X0 s8 C                                        "Could not set char size!", "Font::createTextureFromFont" );
9 N: K; A& J0 m' }, S& n8 V. i
1 M$ B( ~+ z& u# b% U) ]  $ Y' y. t3 t- C2 Q% r

  W9 P8 P5 o6 j# c9 H                                return true;3 g+ q* \! @! e
; l+ {& @1 n" ^4 v
                        }
4 ~( j. X* w6 ~" ]+ f( d& }
- D9 S& b1 H  Y* u5 j9 X) b# T( B                        inline bool done()
7 L1 I6 P+ z6 z2 _- |" F1 @6 H+ N1 p2 P8 M8 f! g
                        {  y1 v" g6 n- q

( E  h6 H% m3 q3 _                                //在Font的解构函数中调用的,本来应该调用下面两个函数,但是不知道为什么一调用就出错,不用倒没事。 8 o2 ]( l4 m' s- d7 C. _, V
8 K( U8 ~, H8 E. E. T" `# u) M
                                //FT_Done_Face(face);" J. L5 g) S5 M  ?' G# s
+ X9 y; {: X! [) U
                                //FT_Done_FreeType(ftLibrary);
* r5 P0 A2 u% W. Q& l4 X/ Y5 h9 _* y+ ]. \
                                return true;, m1 f9 S8 H9 E0 z4 D2 o
% R1 f+ j9 g+ w! {- f1 N: q
                        }8 L& F) D4 j/ b! f# \$ g, \( ^
7 w+ g; W" U2 [& V
                        inline bool getRect(Image::Rect & rect)//这个函数以后用的,是用来找到可以画字的贴图的空的位置 7 N. r2 R% I! i( v* E: u
3 R# D5 f- Z1 Q* \
                        {
' A% @9 i1 H! ?) W- ?
3 m$ u/ ?! L/ |: Q" w                                if(511<point.second+max.height+char_spacer)
+ ], @" }) s: K# q6 P
; d& R$ W$ M5 G9 K- [2 h- O( G0 R                                {
  r; V0 r9 y0 ]. K( G; D9 h, ?' |$ c/ D! h7 Z; U3 F
                                        rect.right=rect.top=rect.left=rect.bottom=-1;
& s" P4 s" g  @: S2 N" P
0 M! k, `0 R1 O                                        return false;
5 k! s* X1 U, s# m: V: K
# `# _0 O% f$ i! h: y                                }! c! p8 c$ Z3 s0 @5 _$ k. D9 w% Q
) f+ q; M3 B2 a' p8 m1 V5 y+ Q6 Q  D
                                if(511<point.first+max.width+char_spacer)
. A. Y, \) Z% |: n7 r# l3 m( V1 d2 O* R
                                {
- c2 K/ U6 V. t, D2 W. a. Y2 i/ e$ ^" w! Z8 ^8 |6 J
                                       
* Q3 C5 _8 K9 A% ]- I8 E5 z( ]( E2 _
                                        point.second+=max.width+char_spacer;
" Y" s' r" c5 B0 V% u- {( V% C
& d9 H2 ~/ ?  L, T7 Q, R" ^                                        point.first=0;3 l- u% O+ K/ D! v1 n( T/ M

' q2 K& |3 c- N! B- O# I                                        if(511<point.second+max.height+char_spacer)
  ]) Q2 n& @! M2 ~  P7 _8 \2 |" r. H4 D' }' \& V
                                        {
$ \8 Q+ o: P" l1 I3 D4 b3 P$ M& O9 p: `9 a' w& _  V' A8 b+ V
                                       
' |8 I% b6 r8 g. @% K2 R! T
4 i9 s( ?) B2 q0 O+ M                                                rect.right=rect.top=rect.left=rect.bottom=-1;
: l" m, k( x& O* D1 ?5 [' L: m/ N4 P4 R1 Y8 g0 |2 K) D/ G
                                                return false;" t9 ]3 d! P. U7 n
4 p- v, ~- Y; U1 r/ d4 }- m
                                        }
( @* q& J# l1 h* K' E6 G2 I
8 P) ]; l/ g$ x2 x5 r) o7 J                                }
7 H3 q: }% W5 L) N; p% `* f, r" E! b5 I
                                rect.left=point.first;3 E; ~# l3 Z/ a1 b
: T' [5 l, i6 P0 H" [, U  b
                                rect.top=point.second;5 s) R) }# m$ Y/ p

: U8 V  v3 {" m* Z0 ~4 G! z                                rect.bottom=max.height;6 o' }# ^) S! i: @
. i# S) c5 o1 v5 o# U
                                rect.right=max.width;  q1 `, G, x' y0 i$ T  x% Z+ |8 l
! k# V5 l: d' {5 L
                                point.first+=max.width+char_spacer;
; k, _2 a. X3 j  t
% j) ^& ]8 U: ^. v! h6 M                                return true;! D6 `: o$ H# B( v' p+ q
3 t0 W3 O3 }$ x, l6 z9 G% R, ?  R
                        }
# w% E0 j5 D; [7 i* y
0 w! a; h5 y) I                };: x% _$ F* y; _# q. u

$ [/ C, ]# l7 f7 D        上面的类定义在Font类中,在Font中增加 TTFMsg * mTTFMsg 数据,并在构造函数中 mTTFMsg=new TTFMsg;( L1 o, E( Z, v1 U2 j0 Z! E

. }/ z; a7 b. c) }( f4 g7 l) Y( n# A        & K( \9 G* @# M& X

% x( u4 D( s: m        正是修改void Font::createTextureFromFont(void);函数,主要几点,首先是分离出很多变量和构造到TTFMsg类中了,然后是贴图从2^n*2^n变成固定的512*512,为什么要这个数字呢,因为256太小(废话了)。能保证512*512大小的文本区不会出现不够画字的情况(所有英文+符号+没有重复的汉字),这个安全区域基本上是够用的。(什么,你要画满屏幕的汉字?哪你自己看着改吧。)还有一个重要功能是,要找100个汉字,找出最高和最宽和最大空隙作参考。修改完成这个样子了~+ D2 K1 y3 v' E- x
  Q, B& t( H; l! H& _
    void Font::createTextureFromFont(void)
; j0 \  M6 R& X7 t
1 J$ i) ^6 W  g+ @: W    {+ ^5 d$ T  j) b% U3 h
/ D9 D8 n- w) k; E# u# X, z( B
        mTTFMsg->init(this);//初始化FreeType2. v# u9 ], n# V7 h' P/ x! e

: _: Q1 w$ F, X* K( o7 [# s        uint i, l, m, n;' ~. x. j  r" b

) L0 S7 l" h) E% _) Q/ M0 L# y! o4 l# f        int j, k;3 \& V: u* D$ y5 t- e' a

) S, Y# S. m1 U6 F- I* V0 C  3 ~1 R6 N$ Q; \
) C5 i3 k0 f- o, N) j
       ' e4 e$ G' C( Y- Z* V' l
" g& d9 S  \) ^" {1 ]
        FILE *fo_def = stdout;//啥意思?我看不明白 5 k5 c8 E6 z+ a5 A7 e  \
5 {/ u$ \% Q4 p4 H  }8 g
  
/ _0 ^; c0 _. |* o& X( S- ?' M; Z) l, m9 h0 j0 h1 i8 ]
        int max_height = 0, max_width = 0, max_bear = 0;
+ w! Z2 W4 J) b, p9 S+ L; k
! x4 d* q& T$ a8 G  
5 \' s4 t8 O* ]) b" C6 C, c9 @& D* A$ p
        uint startGlyph = 33;+ r6 T6 m" `, S/ v

% J! j3 i6 z4 E, A        uint endGlyph = 167;, w9 h$ C6 O: [2 J- o

2 _* a8 y" s. F) b) O2 ]1 X8 {  
3 I6 h8 [) u4 [" X
- E  p( {. i8 o        // 找英文的找出最高和最宽和最大空隙
$ R% q0 I, v2 g. l% f2 ^/ R8 _1 ~: X# v. {
        // Calculate maximum width, height and bearing
6 o( d* N4 s* c+ t; Q, L6 C# ^0 Y. \
        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )
; @* I7 ?; R: T, h+ |" M3 S% C+ U* Q0 _
        {
) L& K! w  ~- `* Q$ O8 E
8 S% g' ]! p( m2 a            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );% p; v9 x8 N* x: Z' R7 v( v
: z) K1 I6 r- K
            //以后的 <<6和>>6都是FreeType2中的数据和我们使用的数据的转换
0 L, |' {8 V* k0 @, p# H2 F9 `6 _; e0 F, u' S- K3 P/ ]) T
            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )
, j3 Y- y! q' \5 g( O
2 I2 j. c  L* ^, @; n/ S1 L* X7 A: p                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );2 ~5 s# v0 `/ v$ X4 V  W" [

3 c; |: H  h4 a! @% O' T            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )( q4 D9 i3 \" a2 i

6 b8 Z1 `* a' _2 S: n# p                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;
0 ]- W. n& m8 i9 m% I0 E- {
+ G- n' M: o, X4 [5 X# ?  
3 ?- J+ B8 @2 \6 [1 J" ]0 B+ Z& @! C( ?2 v
            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width). Y6 {4 s% Q) S# W* I3 e- _

  o, }3 |# h+ }2 G6 v0 @                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );+ l: n5 b% D( ~* k' _) {! r* F
- f5 U+ j' M. c9 u( U2 s
        }
! D% m8 M& y, I- w% {4 F; F" Y/ a' u) f( Y5 w& t7 e5 J
  # e, @3 r  n" L7 p4 a" S
: I$ A( Q. p4 ?# p% f
  
: w8 b# W7 e; w( Z
$ I# `. q- J$ r) c6 Z; z$ d5 h$ R        //下面的for是找100个汉字,找出最高和最宽和最大空隙作参考。姑且认为最的汉字就在这一百个里了。
- X$ V) M3 L5 M7 `9 g: D  x/ H& ^  ?
        for( i = 20643, l = 0, m = 0, n = 0; i < 20743; i++ )$ x; u' a, F: c$ W0 w; ?9 m
( u) q* [2 E) b' R8 [
        {/ F" y0 T* O5 G. Y! `% I! ~
, b  j2 z  x8 }  R" \& b
            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );
) w: W; W1 A2 Y$ c
* ^. @% g4 I$ C" K; c0 t: w  
6 R# i  t- ]* b3 H# \/ f! \9 q
, u  B4 U6 r# |" v) M* ~            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )  w* w; W6 ~9 Z6 T, V: e5 l
/ h' r1 E$ o) ^3 t5 y& R
                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );
  n+ ~1 \, p2 c" X  g2 L9 c% Z" A" o" z
$ T$ y  U# H% v# v. a3 t) X* g" C            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )
: x, f" o5 c+ l4 y/ ?
. g7 C0 ~. k2 c- k0 K- I$ `9 Y                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;1 u8 O! o/ R2 ?
8 R. |/ D) j3 l( d" Y& ]# ^
  
- c( F/ W; M/ A4 |+ \2 C0 w9 }) X! n" H
            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)0 ]$ L! c) Y% j+ d' v
: ^5 j' P+ p8 Q1 D8 N
                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
' W7 u4 {! s* U; p0 |9 Y7 z! H1 A* o( a3 r* ?9 J
  
1 r+ |% H- m+ h  X, C4 k* Z# ?, h( z- g' ?" H' o
                        ! I% }7 c8 [* O0 e  b
0 H, j- D1 x, z
            if( (mTTFMsg->face->glyph->advance.x ) + ( mTTFMsg->face->glyph->metrics.horiBearingX ) > mTTFMsg->max.width)
: F; F+ ]  X5 Q! w1 l3 `+ ]. |" p% ]$ y/ _& x
                mTTFMsg->max.width = (mTTFMsg->face->glyph->advance.x  ) + ( mTTFMsg->face->glyph->metrics.horiBearingX );! R: y! o# G/ U# g) g3 {- X

7 Y$ r4 Y9 @0 [8 w  \        }
7 ]2 I' D! Y4 j+ G7 g
6 L$ e0 _* ~7 @/ u+ q0 i  
$ L( d6 g6 u6 }5 m7 ^( N5 ]" T1 H4 T7 Y! Y6 A8 U) X. |2 n' [, m
                //下面几行行不需要了 我们要512*5127 ]3 t, o. c4 ~

. i9 U2 j5 Q+ c$ t' F8 W& N                size_t tex_side=512;//就是这个了 512" s) _% c4 n$ r
6 l- L  }6 v8 O
        //定义数据宽度 因为是32位的位图 四个char为一个像素,为什么要位这么大呢,难道不能用8位的么,我尝试着改来着,不过改了之后就不透明了。望高手看看能不能改。 6 w( F, a0 I/ ~* q( G1 ^# h* i
5 t# U3 S& I# z5 p4 X1 ?) D
                size_t data_width = tex_side * 4;
; V+ x* ^! |- z( f0 J; g8 E) R$ c+ m: M( I" C: F+ c
  , \, f+ t. L& Z1 B: w
3 {: @' ]) z' i/ y4 w; @
                LogManager::getSingleton().logMessage("Font " + mName + "using texture size " +6 l2 z2 w" `+ A0 H- P/ o

0 d; `# s- J; k! ~- b: V. B                        StringConverter::toString(tex_side) + "x" + StringConverter::toString(tex_side));
: u" I9 p" [! e$ \' x! X  X1 A; W! _1 k) F& H& S/ U
  
# U  u2 l7 n1 B# y5 h. @& ?( o3 A
        uchar* imageData = new uchar[tex_side * tex_side * 4];//设置一个空间用来保存位图 3 a6 I2 w" P5 L& C3 o& _' ]6 L
- A" G9 ~0 K; d7 o- L: {
                // Reset content
) l( Y. W1 z0 G  h/ ]) z
* e4 K& d% B6 e1 h. s' S                memset(imageData, 0, tex_side * tex_side * 4);//清零 . L6 Z5 ^( ]2 u

3 M: E: x$ C1 h5 k1 N3 |  8 ?" ^/ \- |' N) `; N- [* M
& c" V, R( H# E8 m0 u* g9 i; h. q6 {
        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )//遍历每个字,
: Z5 K6 n. `. p+ M& M
2 f( c9 R0 H  Z' Z6 ^        {- l* O9 D- e8 E* Q& ^( R0 }: B! M

5 R( I8 o; j9 _                        * u- C1 h& I9 g" y% J" p! M$ M

4 N. A) l* |& H$ F            FT_Error ftResult;: `/ _- h7 I' n/ d( W
5 ?- S* i, `# i! A0 L% q
    g% R' \* o& l' K8 r  S( E; o" R

" @8 U; e2 o3 G& M! H0 w6 P+ H1 f            // Load & render glyph 0 K4 B9 |( g- P6 R; V' Y; c
6 z4 c% D* _$ {2 |
            ftResult = FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );//读取字体 1 s2 S- e9 G' G* u5 W) M2 m! ^

  p8 W7 k+ A& c# k6 m6 P            if (ftResult)" N  k& J# a% ^
, {) h# x+ w' K; J/ K/ k* g0 V, b
            {7 h/ ~) Q4 j1 q( ]9 z8 g+ A
& H7 Z1 E- V5 ?" c; |4 `2 D* l
                // problem loading this glyph, continue
5 g  Q  P% y/ @" a* }! b+ c9 t. _1 ~7 s( @; B- o
                LogManager::getSingleton().logMessage("Info: cannot load character " +
+ T# o% W& o% ?* n/ `
$ s: z* r5 u8 R% A" m                    StringConverter::toString(i) + " in font " + mName);
5 y$ t8 s% Y- Q! i* s) y3 @" C3 c& G# ~
                continue;//如果错误跳过 , _. u3 E" t, p4 b- L

2 w5 j2 m7 @  O7 w1 \9 b! q            }
4 X1 s4 {; t& M1 o  y2 A( ]3 V! i# ]' \' ]
  
4 ?+ s# Q! \6 y) f
( F/ c9 Y& C7 s% [( V* [& U                        // 应该是字宽
0 }! {9 `( D. s# T4 u) p; j3 g& b8 F7 O8 G: l: o' |
                        FT_Int advance = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );6 C. _+ q% f: `

7 Y+ _) l+ b  e                        2 s" C- B# B0 m7 c" [
  Q. o3 _. @5 l" m  R4 u8 n0 g
                        // 得到FreeType2的位图 % h* G  N% J% O7 [/ t8 ~: z
1 i/ y7 u- i# x4 Q6 A, A! t# k
            unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;
" D3 M1 S9 |( ^+ D4 n5 y/ v( M# @4 g  S% s- |( f
  
# w6 {3 O, a( D1 N" q& E" h5 f- u
            if (!buffer)
- C, U) ?! A! d; L$ ]( v: V
1 M* t5 _# U1 @            {
9 D3 t* L( W* e! h! m; a( c# Q+ @7 W* A0 s$ E# n' G4 L- k  n+ s
                // Yuck, FT didn't detect this but generated a null pointer!
! g: e$ `3 O3 n  O% A
1 _1 e5 R1 @/ M; g6 h* J% ?                LogManager::getSingleton().logMessage("Info: Freetype returned null for character " +* I! w' s- H0 o, g- ~( V+ h

! S( p8 O7 J  u1 T                    StringConverter::toString(i) + " in font " + mName);1 O0 [! G; n+ A7 z. v5 {
+ h/ q. [& _3 ~0 |5 a8 k
                continue;//如果得不到跳过
3 Q& T4 i, z6 A' L& r7 H
' K  b; O: K( S- d9 p  R            }" n8 N8 ~" ~8 {7 H
4 d* Y# }4 W* }  e! r% e
  
  r8 V! @8 }, h, a
$ }" {9 I2 _7 h. P  b                        // 得到y的空隙 (最大空-空-本字空)就是说空出这些字底部就平了 , j, C" K3 n, _; e9 @/ U4 U
% d  Y  \! {! C0 n, ~0 x
            int y_bearnig = ( max_bear >> 6 ) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );# f  [# e. y% Y

! Y1 ^9 Q$ k- l" a% I' J- c                        
* z3 q9 I; T. j$ N7 \; S- `/ j) Z5 ~0 ?( u& L; Y7 L% @! c0 ~( ^
            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )
& t  q- Q2 ?9 d/ D- l0 m( h! t% f6 l" M' M+ X2 `
            {
6 \8 j  u5 m) ^0 h# T$ F% V$ N* p) }1 |# B! Z0 ?3 J" n
                                int row = j + m + y_bearnig;//相对行+本字在位图的总行+空隙
" Q; Y) R; @. G6 x
5 }. J3 k: O$ _; t$ k                int col = l;//列 5 t# w# V3 L: Y+ u

5 A; @$ u; W! J- h8 S& H& O                uchar* pDest = &imageData[(row * data_width) + l * 4];//找起点   # }$ d0 G! [6 k4 `

+ d; e& N2 s$ m# ^5 d                for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//画图
% K5 c1 B3 g8 M* C$ c
! d/ a8 y6 ^4 |9 y3 S* }" s                {, F, Z( S  X3 g0 G9 V% y' K" V
& V1 b& s9 M+ R2 E( U6 Y
                    if (mAntialiasColour)//看不大懂,难道是灰色字体?
* N7 o8 N- V: H. J8 n- B' |) I- o5 H0 q
                    {
/ I- i; \; M; j3 E3 ^+ W4 S7 l) I4 E" G/ c, G
                        // Use the same greyscale pixel for all components RGBA $ b( I7 K8 ~  {4 z5 m

/ O, ^' p- h4 R% l2 K/ A                        *pDest++= *buffer;
: C& Y3 y3 E1 b6 Q' E: r! s! ^* L
- F8 r  D" u; k3 C                            *pDest++= *buffer;
# x% |1 a3 E5 c( m
" l" r$ K$ q, U; \                            *pDest++= *buffer;
. y# [8 [0 `# c
, |: ]8 p& N5 F                    }
) `/ l* T# W) W2 A2 ^: ]- r' T$ @* \" Z8 d( z) r- N) z
                    else
! C2 N- o+ g& P, w6 m6 J% ^( x% L
                    {6 f% b, Q: ?7 K; @. s
: k) f# N# }( |1 D% z. p. l
                        // Clamp colour to full white or off
. z* r" t% ^. G1 ?5 Z* [1 W6 c1 o5 G3 u3 O! a2 @
                        if (*buffer > 0)6 F# Y4 J4 p5 F: ?) w& R' F

9 O; T! u: A$ ^# }0 u1 P                        {
3 o1 H. F+ v4 e/ |* R* p3 k+ N& h9 `! ]7 |% F  z4 x* l& t
                            *pDest++= 0xFF;
5 h1 J' N- w7 ]
5 Q& A: E3 P3 k% H' G                            *pDest++= 0xFF;
1 e5 r. A- v- d3 S
9 }5 {( ~4 ?" s; e) p+ y                            *pDest++= 0xFF;9 C( l2 G! q  f* T7 N& {" ?5 b. V

! Q+ d4 _$ ~+ w5 c) b6 n                        }6 e4 M$ {& L: P3 d4 t7 D( _

" ?- S) e& k! ~6 i# E. B3 G" E                        else
* a( \* u& `2 X& J
1 w8 V1 x# W. h4 Z0 }7 }) v                        {
" ~7 {2 K- f2 A
7 \2 W$ B4 v8 P. g% c                            *pDest++= 0;# C% z* R2 z9 P
0 z3 D# Z5 r" N
                            *pDest++= 0;- n% H) _  K+ B# o% F  `& T! u
. r# x+ U* [, j3 n( z2 ^
                            *pDest++= 0;
2 d( g1 q. j& B5 P, ?; g3 g* o- w  o3 a% Z1 K" u5 l" p
                        }0 V/ I# U3 H5 M& x7 W
5 v  j5 F+ S& ~) {$ X
                    }8 m2 X5 _) s' K, M1 ^  _( |+ {

# i/ C& L) G, Y6 z( b4 S. z" p4 K9 U                    // Always use the greyscale value for alpha
0 q3 O; }2 b4 G5 C/ B5 p; H
" h: z/ z5 E7 C3 j                                       
+ T& n3 i- g0 m, Z+ y  c, h4 c3 b
6 u3 @  h7 H$ ?/ U: Z5 I                    *pDest++= *buffer++;//alpha! 我是一点不了解了为什么是这个?
; H& ~* o9 w7 t  s  O; A, p+ ?5 \& Y
2 Z4 [. W. a* E' b+ f3 m; w# s                }
0 K2 u! N2 O5 h4 ?
4 `7 y6 t6 e4 `3 ]            }
3 D; \, F- y' `$ p& M; X# |( V9 y- t( x' E* M
  
; m  |$ S7 J2 {) Z$ w% C6 g3 h6 @$ y! e& C% @! K' e) D, |
            this->setGlyphTexCoords( i,
8 W) c5 q0 C, z% U3 D% p: l' l* L% X6 b$ k4 _# o7 |5 e
                (Real)l / (Real)tex_side,  // u18 e$ `3 K" o" C9 R" E# @7 C3 Y7 G( Q

/ e1 ^& R( C$ X- k) _* I9 D3 |7 H5 C                (Real)m / (Real)tex_side,  // v17 ]. @2 }) v- b7 k
9 P7 c1 X, K5 m7 \
                (Real)( l + ( mTTFMsg->face->glyph->advance.x >> 6 ) ) / (Real)tex_side, // u2/ `9 s/ y, p  n; V7 l2 ]
& k& a& l5 ?9 [( R" \
                (Real)( m + ( max_height >> 6 ) ) / (Real)tex_side // v2
- {& ?2 e% L  B3 w; w4 K9 V0 b- l4 |4 \+ M- p* g
                );//设置坐标
: j! y: h" N8 S8 R" ]* p: m( }* K- [( B
  
, _) Y8 ^, D: |9 R) ~; c
- F5 S! a& f, K; P, ~4 b6 j% i- l            // Advance a column ) @& T. _6 h  d: e
8 N4 [6 x) |0 L1 x" j4 O3 ]) l- ^2 T4 r
            l += (advance + mTTFMsg->char_spacer);
) ?) n" L$ F8 n# d8 b! P8 m4 c$ I5 p, k: B* S' H
                        //l+= 本字宽+字空 ( K7 y) a/ ?" m" W

, F2 x- X4 D. w  6 J0 w& g9 F) E4 x

$ y3 H) d- ?4 E/ ^  @            // If at end of row
/ t2 ^" a7 ^; g- O  ?0 E* Q% J& ^9 b
                        //如果到头容不下一个字
) M4 H; f) s+ `/ \
% m+ ^& v# J6 S            if( tex_side - 1 < l + ( advance ) )
5 Z9 I! S) Z, X+ t; b6 x4 h  ?. v' f. G  g, s7 q7 W
            {
7 V6 Z9 E' F# h
* j  G+ {4 L0 ^* [                m += ( max_height >> 6 ) + mTTFMsg->char_spacer;& w% S- f- S& X! s& b7 a

5 A) V% L1 m2 ], h+ T$ N& X( R; W& x" y  I                l = n = 0;
$ ^7 z% I  x" s9 P6 w+ M" q# y2 g. [* d3 M
            }4 g& C9 k4 A& `: a: f

: w6 x6 B, ^! T. z' M/ d1 n  
; l8 ^5 [. Z) B4 D
1 V) x6 K# a  [4 g7 C        }% E+ N  l0 s) F
2 b0 R( C8 s) F* L) F$ b
                // 把信息存到我们的mTTFMsg中 >_<8 G; V1 P. g* R- A3 f

; }+ N" o& j6 L4 i! D                if(l)
6 y# a# }/ _, N
/ l; e: l! m% `- \0 R                        mTTFMsg->point.second = m + ( max_height >> 6 ) + mTTFMsg->char_spacer;/ y- O& }' h6 g* P

+ v; O4 L8 o: d3 l. z) v                else
2 G1 W# o2 r% U' W* v9 E8 Z! m  Y) E, K7 F$ Q
                        mTTFMsg->point.second = m;
4 t5 \" D/ ]* h$ U! v
/ L( }9 f5 w# h6 i8 |  
3 `! w# \# R6 ~9 N
* O9 s$ L; t4 j                mTTFMsg->point.first = 0;//另起一行
3 G1 W" @; Z  X2 l0 P
# S3 p2 g7 `3 P/ n! _4 Q8 _3 X  6 k. `3 v4 j7 X8 }  H

- A: t  `; Z  i5 V. r1 Q$ d                //下面是保存几个最大。 9 D" ~& w" M* I: v7 a0 x* s

9 n& f4 Y0 O' |0 v1 D8 p                mTTFMsg->max.height = max_height >> 6;
7 I0 y) V4 ?0 U# _  ^& L! M9 {1 a3 g9 v9 j( G- O
                mTTFMsg->max.bear=max_bear >> 6;
5 T4 u2 }" }( d) I& c+ t+ P( k' v# I7 B' X; M; F0 g
                mTTFMsg->max.width=max_width;
, M, v$ w1 `" A# {' W
# r* l; x! W+ Y. p/ w6 F1 @  I* v$ e  
3 g- W$ g$ z3 k  f  J; D! f+ I3 v! i4 h; A
                mTTFMsg->imgchunk.allocate( tex_side * tex_side * 4,imageData);
/ x0 s" z# b1 G, e2 k
* d/ m. N4 q) c: Z2 V0 K5 B               
+ A4 D- p, u. R) O; J* \
5 ~6 f, c9 v% z, }                //不知道为什么要设置img这个中间变量,似乎可以直接从chunk创建贴图 ( [7 a; Y8 o5 W3 J

4 j) J3 L7 L- h$ g        //--Image img; 0 Y% N6 F% ]  |. S8 P$ a' {
$ S5 M4 V- O3 ~; Z7 I" I1 e: `5 ]3 r, w
                //img.loadRawData( imgchunk, tex_side, tex_side, PF_A8R8G8B8 );
& b- N) a+ _( H, }+ k2 k6 r7 {/ \2 R+ [" f+ s& F# A
  
: M. a6 {. f' c* g0 E9 z( y. q! ]7 I9 S, w* T9 M) L0 r6 v: r, \
                //贴图名
( X5 m  a# R2 k
) J) Q8 j5 I) e& l        String texName = mName + "Texture";7 M! ]7 d. S1 J3 N3 A4 Q$ H
% E0 G7 ~% F1 k% b3 N, V9 _6 P8 S
                // Load texture with no mipmaps 2 c' G' T7 A- Q; l
" \4 O" l: s# y/ ^8 m* d! L
        // 把从img创建位图改成直接从chunk创建贴图 6 R" t/ \( o5 ?" _% c

( I) n4 s# _' V: @" e* ^                //TextureManager::getSingleton().loadImage( texName , img, TEX_TYPE_2D, 0  );3 T( G7 j0 C9 T# r
2 S9 `7 G9 M& {
                TextureManager::getSingleton().loadRawData ( texName , mTTFMsg->imgchunk,tex_side, tex_side,PF_A8R8G8B8, TEX_TYPE_2D, 0  );2 f7 c& U$ w8 n

; `( J, U: w' L  d  l9 a        TextureUnitState* t = mpMaterial->getTechnique(0)->getPass(0)->createTextureUnitState( texName );4 p) C$ f7 @, c+ g  V9 }
1 Q. {) D% n! `! w4 E& H
                // Allow min/mag filter, but no mip / ]7 O+ V1 K* V

$ B" X$ j" e9 v                t->setTextureFiltering(FO_LINEAR, FO_LINEAR, FO_NONE);
* G: t4 _: @/ x& ]& E; n( j, \7 \3 G1 d
        // SDDatachunk will delete imageData 2 |7 o" P' {; K& E
7 L" g( ^2 s  u- X0 K9 F* J  ?" Y
        . M6 }# X, |4 ?) K  M: N9 h: G
; |& S- N# q. L* k* Q
    }
! U) L8 N% t( N* N& ]9 w' v- B4 G' h' r5 O1 B0 p( e8 J
        你应该对照一下以前的函数,改了很多的。 8 U- J7 H9 @: u' M/ }& o0 `5 v

0 T% y' V  T3 z8 I' G' v: q  ; G2 X. C! r3 }

# d# W- v5 H9 @: E" a) H3 ]6 E  
+ `% @' i+ z+ o; l8 [
0 Q* _: `/ L4 J/ [9 P(3)
1 f4 R) y8 c5 z
% v9 l& E" J0 D7 H# I9 V* {' O        然后最重要的是动态的申请和画字。
# k$ d4 K9 s! }; Q! v; D# J/ H' Q4 T' a3 V) O* H, f
        首先最重要的是我们要一个方法得到汉字的unicode码,我们用到了unicodeMap数组,提供了区位码到unicode码的转换工作,等一下提供这个表给你,好不容易从网上找到的阿,可惜这个表没有中文标点的对应,如果希望支持中文标点,就要努力找到unicode码并加进这个表了。这个表是这样的 char c[3]="邸";unicodeMap[94*(c[0]-0xa0-1)+c[1]-0xa0-1];就得到邸的unicode码,不知道为什么没有5165~5169的unicode码,是轮空么?
: n- ?; Q; U4 [+ Z" u; {
* M7 \) B) }: |9 I) q8 G. S0 f$ H" }        
- J; N5 x# S% T+ o; P+ g9 j
% K; _* J/ V" v5 e        申请渲染(字)
2 @% x( N+ q: J. K  y7 U/ M) \8 }& [( C9 z
        {4 ?% k! u8 B$ F

2 v0 @) `8 |% U# u; D                if(有这个字)
/ V2 y" E$ q" w# [/ t3 c; w
8 _" F: c- o6 ?4 [1 v                        返回位置
' j& j4 B& z+ Y% J* C% `8 c/ a. V, D$ x4 S: v: T" n
                else
; ~9 c; A) u/ |5 N
2 t  ^  N8 W8 f                {" r5 N' f& q' }, g* R9 W
) d& e( R, v6 s7 k
                        if(有空间)7 X1 p# X8 I% L6 N$ u/ n( t+ T
* ?) \/ ~4 |3 }2 F/ d7 o' k( n
                                画字
% D9 \% K2 g4 q! Q/ L* S0 }! H7 }5 r* O
                        else8 W& W6 F: Z7 l  |" `" K& Z$ ~8 Z
; c( L+ G+ P( d  T
                            找不用的字//找不到就出错,没地方画了 # T& l- J) V4 E8 ]# W( e2 O, N
) p$ M& G8 N7 L% ?$ u" j( a# L8 a
                                删除 在这个位置上画字 " a% E6 t2 ^. _; q3 ^: I, [
- g6 W' ]2 e# D& |7 X- L
                返回位置
, U. N3 }3 |% H' b4 |4 N& p- U+ j  ^: h* e6 l: F( N1 M
                }
5 f8 ~, a2 j: B0 ]3 n1 @; e) [. S
4 y3 l6 \# w- O" W% N  m        }, w4 W4 q/ d1 b' f1 m; [& p( A

0 N- v; y' J0 w8 w& t; k        上面很直观把,大体就这个意思了,申请渲染的函数是inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )  const。去掉const改一改。得到
) W* G) R7 ?2 a4 Q0 ^7 q( s2 i
0 I) l% Z% `7 g! W0 d        a.申请渲染
* W4 f1 K  Q8 e7 H
. A3 F5 b. W7 H$ D- @        inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )         & d) u5 }5 I' C/ L
+ H( r  @6 c7 Q4 F9 S! o
        {* u6 v. L1 B$ c( h& j( F

& p4 u7 L8 [. o' P: z; g                unsigned long idx = OGRE_GLYPH_INDEX(id);' E' ~7 w' |+ P: t9 k
5 Z2 M0 a. Q$ \) A% t$ L
                if(this->mType==FT_TRUETYPE)//ttf?1 y) E! R# f9 b# ?: X
8 ^( a+ _- z/ R" Z* n. t
                if(id>=161&&idx<OGRE_NUM_GLYPHS)//汉字?
6 t2 V$ C' t8 E" [# Z/ c
4 T) H& Q9 e2 o4 _1 h( C                        if(!mTexCoords_v2[ idx ])//没有?! W/ }& C+ |# z
% G, ^6 s  Q9 E0 p
                                setChar(id);//画字去 ' U9 A/ d6 o" Q7 I: S2 d+ q
/ m+ h- M& J  Q
            
1 I, ?, N4 ~! N# s% y
# G$ j+ A4 `$ r5 V8 |            u1 = mTexCoords_u1[ idx ];
3 @) z0 _! Q' F& U' m5 P5 e0 a# {6 R; D" Y
            v1 = mTexCoords_v1[ idx ];7 I- _+ |6 X. ]  j9 f) \. _. q/ B' f

/ T$ ^% ?: N0 q/ v2 Z% ^, s            u2 = mTexCoords_u2[ idx ];
6 S4 w& i2 F: Y& A5 p' j& ~. O& q  t' Z" T( v4 y* H
            v2 = mTexCoords_v2[ idx ];
% `  L! I' f4 o3 e( d2 F
9 e9 o( ?' F+ g" v        }6 x5 ?6 c* P+ ]4 G  d- ~

* j/ }5 w2 e  S* _$ H# v        b.画字等 ( F+ ^5 H5 t/ C+ v4 q' e$ u

, X& Q8 B' R, [6 R7 a1 Q4 W        bool Font::setChar(unsigned long dwChar)
  z( G! Z+ H* C) r: L0 n1 n3 O" i. m3 @
        {$ ]) D. s9 D% u

- L6 ?9 R8 R) \% @% ~                int j,k;
7 b9 K% z/ ]$ k  l) o- r) D4 f" k$ S# f, Y
                uchar* pDest;//操作数据的指针
7 i- u8 _6 E! k4 M$ v- l) g7 B6 c- j" T
                mProportion=0.8;//不知为什么,总觉得中文都太扁平了,所以设置这个参数,在《让OGRE支持中文》中创造的参数
" U1 q/ f5 J4 ~! j
0 Z2 j4 |/ f1 U' N$ {; A                Image::Rect  rect;//画字的位置 % C+ q  f. f4 B( [+ z8 \! h) h
! x0 I$ L, T1 @5 d; z) B
                if(!mTTFMsg->getRect(rect)/*回头看看这个函数吧*/)//如果得不到空位置 9 C' D" t( F9 T0 {( ~9 c
) N0 N* p- }  d, |  b1 s; L, S
                {
1 i& z4 O2 v8 k/ [1 \
! T$ T% r3 M7 s                        for(int i=161;i<OGRE_NUM_GLYPHS;++i)//寻找不用的字
" n) w! `9 K' l8 z. Z- R) o) O0 M, X; j* |5 u
                        {! ]( T6 x' |+ }  J

0 i5 A) u# ?6 m- a                                if(!mUsing&&mTexCoords_v2)+ s) v+ C5 V2 P' i5 M' ~  c! w$ c" q5 V

, g& P. q! W5 ]9 g& M% f% H7 F                                {* N# s, a4 s  E. D
) L# }# x7 m8 l8 ?* M- _4 l! ?+ L
                                        // 得到坐标
5 H% P: I  @: B1 R5 ?$ H* T0 w! l, m
/ j5 R: h/ m3 O/ X* `* Y. J( f9 A% F                                        rect.left=mTexCoords_u1*512;
% u% }. S+ G" x! f8 v  U6 ?9 S  Q4 Q2 f8 P$ C# C1 k
                                        rect.top=mTexCoords_v1*512;) D: p& u8 j; f! F1 ?

2 [9 q: l6 @3 E- u! m! V7 m; P* L                                        rect.bottom=mTTFMsg->max.height;
) T9 I2 S" e1 n5 ?$ P( {7 R# Z6 `! N( }6 n% M3 x& i
                                        rect.right=mTTFMsg->max.width;
! U0 J0 z& O+ y2 G
8 U1 {$ G/ n3 X- S% Y  2 v8 A. Z- M  q5 x% S

( o$ F3 g( Z' ^- @8 z7 X' ~                                       
. s. R# c# r) O! q
; q: l$ d; F! n# P5 C: g                                        - S7 x4 J3 {; O  P# o; D
2 n3 q5 j! u, Y
                                ; s8 |9 G5 A/ ~; h1 G8 |" a% ^

4 D' x/ L6 y9 F- t  T- Y7 `                                        //擦除(这段代码没有试验过,等做完输入的类在检查吧) : m, j& Q# C$ J, d, o

* ^. @0 H( n% F" x: j3 w2 K* ?5 p! c                                        for( j = 0; j < mTTFMsg->max.height; j++ )2 B1 g# O# a8 R4 n
# o9 i3 P+ {( S- L' J- J% S! R
                                        {/ j  x9 b! C! A8 w' w' S

2 y  S) f$ }$ V4 `( B                                                pDest=mTTFMsg->imgchunk.getPtr();* G% y$ F  q  v0 Q! b, @
$ [3 o6 Y% h% D  V2 a1 |) z
                                                pDest+=((j + rect.top)* (512*4)) + rect.left * 4;5 g; V( v: m5 H) N" b) Y
  h" ]+ d$ p4 G% W
                                                memset(pDest,0,mTTFMsg->max.width*4);( c9 [1 b) n' n/ w" Q
# s, Y, K9 D3 e- C6 N- g  ^$ E
                                        }
) p8 J5 ~: K) r; \1 Q& G! o: o5 B& S5 _
                                        mTexCoords_u1=mTexCoords_v1=mTexCoords_u2=mTexCoords_v2=0;7 ~' p+ U" M) @/ [6 O. `- u

# w' a5 |5 m) _/ G  
* d; w% Y$ B& R- A" T" d
$ P) q, U9 v$ e9 T+ m4 [5 C+ ?1 Y) P                                        break;
: D; N& v( x  I1 {  k) K/ m" h$ f6 C2 f
                                }4 z* Q0 u# R6 r# `) Z, l

# m8 p8 Q. u$ R/ _  O+ H                        }
$ N2 [& H% s, g1 ?
6 m# s( u4 N: Z3 m% Y2 U                        
' f7 `3 T: a8 ?; V7 Q0 P( G' Q3 |  i3 _# i
                        if(rect.top==-1)//啊啊啊啊啊啊啊啊啊,贴图竟然都用完了,没办法了,出错了 2 A: U. S# t8 k
& M( P" k3 {; D# V9 h8 E( @
                        {9 b$ n) o8 J3 L
6 @) p" W9 z) m; ^2 U  Y/ a' C
                                LogManager::getSingleton().logMessage("你太贪婪了,用的汉字太多了,这是对你的惩罚."); 8 t1 L' U) ]; R& W3 l2 p6 Y8 G
+ Z3 H9 T& ?  _
                                return false;
, q& w# Z, ~8 }
( i" _% S# Q! y  V+ `* m9 M                        }# L0 u5 k. z$ R( h) c0 z; W+ J

# P! U  Z" O0 {! t  Z        
2 H( K. {, N  R' M% L
4 {" R: v" k& n& B                }* v) R/ q1 N( f$ f! w* F: P2 J3 P
' [! g" `( X9 a7 b
                        
3 }) F$ G# Z8 N! t& U
3 T1 x# q+ ^% \               
$ L. K+ h9 r$ i' _3 s! n/ V; |  Q; c1 E+ Z
                  //以下画字的都是招葫芦画瓢的,
# P$ g. Q+ n2 I5 V2 Z
/ f5 ~6 O! W( C, J6 q/ U( V                  FILE *fo_def = stdout;
4 ?  q+ \! r+ T0 x4 k
* X8 ]  _2 D2 L) o5 u* a                 FT_Error ftResult;
& L' B# v$ D+ R( h+ R
: l8 i, a- P9 V9 y  
2 A8 E/ L! S0 k) \9 k- F/ R; N
$ N! p+ W( _* o            // Load & render glyph ' c4 a' k3 y" x# k+ c
% @  l  a9 V7 ~
                  9 ~& c: t$ X& X/ U& V
% T3 a2 ~, S- G& j  e
            ftResult = FT_Load_Char( mTTFMsg->face, unicodeMap[dwChar-161], FT_LOAD_RENDER );//读取字体 # M- {0 E# Q4 b/ M, |
1 r2 N/ w: d0 U1 j1 J
            if (ftResult)
. S; k0 X8 }& c1 a; c. `
) h, V4 B/ k. W, o. W0 U! t+ E+ Y            {
2 N) \& r# Y! h% t( K5 n2 |5 V7 b6 C, U; w3 t
                // problem loading this glyph, continue
4 a& @5 p" D  R& ]4 k9 W, A! i- |. n3 r9 R6 B
                LogManager::getSingleton().logMessage("Info: cannot load character " +
! R! \7 B; _$ K% @! v1 H% F8 r$ [0 x+ x( H9 I
                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);
( H: V& c% v* }# `8 w# F/ P
1 O5 z" |  S% t  T, \  u7 x8 ~  R                return false;//如果错误跳过
& v! K9 r7 }7 d2 B% z: h
/ S+ o3 \  |) r% H3 ?, j            }" `( i% H, p) N

% x. b" `' E' G9 O' {1 C  # }. f" Q$ U" K7 E! v" y
& `) B% F; u8 ]3 B' |0 G3 @: \+ ~
          unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;7 i0 `2 G! W% a, G
5 C9 ?' i7 x$ V% q) K% j* ~1 }) d( f
                  // 位图指针 + d, d/ V, h5 Q- _" W" n6 S1 x3 ]

2 P% Y8 P/ X- b) d, |  m            if (!buffer)8 g0 r: F* X" R/ w! n, P+ Z

: K; }# \- w( O  W# n- A            {1 t# |: q6 y+ q$ t( D9 B5 z

" {" h( `2 N; c+ z7 `                // Yuck, FT didn't detect this but generated a null pointer!
+ i4 [8 f/ v. `9 j0 O) W4 P# Q& s( ~$ _( |$ v4 R! p3 P" s
                LogManager::getSingleton().logMessage("Info: 1111Freetype returned null for character " +5 R, z  e: o! W, u( o
7 l9 e$ J7 e' `( K; i
                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);% }, J; _, ?+ ?1 m+ R4 T

# i2 S; s' {- O* Z                return false;//如果得不到跳过
1 g2 v, H, C1 T% k- M. ~& ]
, p' N  f4 M% ~* d            }
$ l6 ~* r; ?0 d' t5 Y( N* [/ j& o$ v7 s" _+ e: I
  ) F2 C8 R! @4 @+ Q6 R
5 \! [8 y3 ?' S
                         int y_bearnig = ( mTTFMsg->max.bear) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );
5 w$ }. O- g4 l6 ?1 H1 A6 G; _. P
$ }8 K7 E' a1 `0 b       ' f7 N% T( b  ^# `
8 A. X: o9 {) K  y$ _2 N* Q
                        
8 O4 b+ {( [" Y0 o# N7 W2 z  S- N, F
            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )4 P8 w# C! W9 F% M" H; ^& Y, R% |

$ u- x+ v' [; Z. @            {
+ y$ |1 x0 S# V7 \, H( e' c
# o1 l9 B" C, [- S, A  V                int row = j + rect.top+y_bearnig;
6 \( y$ F/ y' X5 d  B  p  _: |) h$ ?5 y! p
                int col = rect.left;//列 ( r: d/ U7 R3 w( f* i: g' M
9 b1 d3 L( y2 c: C7 v
                                pDest=mTTFMsg->imgchunk.getPtr();& Y9 ^! o* c9 c1 }# `; q: f  M

- o* h1 A2 v" G6 v, }  0 d0 ?/ u2 w  p/ V" L# [/ ?
# n' N5 B, e7 e% Z
                          u3 I* l# h6 w+ k
3 j' Q" Z# F/ J- I" @- y) h' Y
                                pDest+=(row * (512*4)) + col * 4;
9 ]2 d7 ^! A- k$ E7 Q. t2 u& k7 Z4 V( l' {, s# X
               for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//每行的点 2 W2 M6 Z" D% `( ~$ {# m
, n6 f- i0 d( t: _3 @* P6 K4 X& _: ^
                {" c0 r# S' o, r' F* c4 [
# `( _  u' z2 w% p  ]
                    if (mAntialiasColour)
6 t' B; L+ D* N3 M: w4 U1 g8 P. ~$ D. L1 q/ D' X; T5 n  d
                    {
& {7 V1 ]' q3 ]5 ]  A$ _
5 e) g' l7 W# d2 N) @1 E% X                        // Use the same greyscale pixel for all components RGBA
9 G6 `5 ]9 ^+ r8 A8 v6 W' v- w5 {9 @0 S' w5 A& ~( F
                                                        *pDest++= *buffer;
. O1 ?0 ~6 P% c0 `* Z: L. i( y7 U5 M8 x" ]9 V  X4 P6 I) t) m8 p3 u8 }
                            *pDest++= *buffer;5 \; U: E* M; J6 S0 g# O* F
7 f' ~9 t/ k4 j: ~6 Z
                            *pDest++= *buffer;) Q+ ?5 P- O% w# S1 l2 ^
% S1 K" w1 R2 i* g: h6 `0 B
                    }# T. @+ A5 I& l. I3 C! j

" l4 j3 h, [3 @: w0 z. U                    else
% V  m3 k. L! B
: A3 W+ H: a/ Q. \, \4 ^1 f                    {
  C6 ^3 I  N  q9 s: z1 q6 H
, Y. A- p# r$ B. x: c6 K& |8 B                        // Clamp colour to full white or off
7 a1 @% m7 S+ ~
, K3 A6 {, G9 M& j& c* I- @                        if (*buffer > 0)2 u& f3 h7 O: c

" S2 _" A1 X* V2 I) z; K: V                        {/ C5 l- _. u& e/ w8 z8 P1 T
; n7 e4 F) n- R) A
                            *pDest++= 0xFF;( r' O7 d- x6 c3 X. W
4 y) A- @! b6 T+ P" m( O) ]
                            *pDest++= 0xFF;
1 r$ i4 s, X# g4 }) }6 F% L$ e+ t% G' q1 M6 d0 m
                            *pDest++= 0xFF;
/ t* @" U* @2 `" S9 n/ w/ U& S3 \0 r/ e, _
                        }; t, \7 |' L4 ?4 x

) ?% I. |$ G3 L                        else
: _9 w2 X$ Z$ A; M, I( {3 I) ]: U' x) V- S$ \) U# F! ~$ H! x6 J
                        {
+ I9 D7 M8 V: [2 J
( O0 v( {0 e$ W1 d0 J1 e                            *pDest++= 0;. v/ N, f+ q+ C2 N% @7 h2 [% T
. a6 K5 n( q- q% `, z4 i2 D" r  g
                            *pDest++= 0;3 _5 D+ j' F: J/ w2 W

/ e/ `1 z# [0 M- J0 J7 F                            *pDest++= 0;- u. a4 k6 i. Y& D+ ^- G' d% _

% o3 |6 b# a) W6 T) b                        }
6 y" p+ f7 u( w' j" S( M$ w. X: m( r' o0 m
                    }% a! {2 C$ m. D2 o$ j
( F  M5 d$ Z9 }5 {4 L+ t
                    // Always use the greyscale value for alpha 4 T/ }" u7 I. U$ d' d: b
- S5 G: o% c3 }% d# `9 E
                                        1 `6 F9 y+ p7 X* M

  x, c# J% M( P                                //      LogManager::getSingleton().logMessage(StringConverter::toString(*buffer)+"is cool");
9 \+ e. V$ I5 z
; q8 c( t2 f9 b2 X                    *pDest++= *buffer++;$ B/ g( J% j3 O9 H

/ d' V) D9 ^, L5 s1 d0 ^' c" b                }
' y4 h% o: i; z' e$ }1 S
" {7 m0 O: M7 ~9 P                                
! C  U* ]9 P1 d& K* c" Q
$ c, s& H( i7 n                        }
' ^' \: }9 H% [' j* }& l9 e# ~% m: X* p1 `6 m; ^
                        // 设置位置
1 f2 F+ I9 ^! a5 l% m: p0 E$ n, M0 n# o) g5 A9 h
                        this->setGlyphTexCoords( dwChar, : E8 p' V. R$ Q+ R4 \3 l+ j/ C: L4 F4 P

, f7 @, {" V! f, Q, T* u9 ?                                 (Real)rect.left / 512.0f,  // u15 @' K- }: ]/ K  U& l

3 i2 v2 }9 {2 S7 t3 j" b/ ?                                (Real)rect.top / 512.0f,  // v16 Z  \; J0 C, |1 [, Z0 c

) e- Y4 V: E! m; i8 J                                (Real)( rect.left + (mTTFMsg->face->glyph->advance.x >> 6) ) / 512.0f, // u2
* a( O) h# |8 G, d) b4 c- O6 N2 _  [& E
                                (Real)( rect.top + rect.bottom ) / 512.0f // v2& p/ w. n1 i  H; M+ D3 r- M
0 g7 ~" a9 h; I$ p* n4 x4 N  q6 k
                                        );* K" u" Z, S2 {3 h4 Q
$ X+ H( ]6 {- h+ s% ?3 V' w2 E
                mTTFMsg->dirty=true;//贴图需要更新
' Q" r5 Z! E8 f: O5 i1 M* u7 c
5 d& r" K* E6 s2 p/ I                return true;
, X  W% K) B7 `& q! @# Q, S- c) l0 _% X/ f' d, o
        }8 L. m0 q0 R" s. E& U/ \
1 D5 k& d5 e+ {7 y6 _) k5 `
  : V1 R/ k4 B. ~( ~" ^+ w: f# S$ q+ d4 j

+ y; y1 y# M1 o- X(4) 3 D) x! s- `, \" }% O
# T* I* \& R$ P7 O0 i+ {
        松口气吧,繁重的工作都做完了,就是更新贴图了。 4 a$ v7 h. z% a  R4 A
" P8 Y% ?& R! d* a, J
        Font类中~
6 e6 d1 ?$ v* E; ?' ]
( A7 m) X/ F$ @& x        inline void write()
- V2 K3 M+ ^( m* Q/ w3 d2 g3 ^
3 r1 T* r  W! I: R                {
: |% T" e# \* @! Q# }* Q+ T: r: t% \$ B
                        if(mTTFMsg->dirty)
) d' D# {: k# F# H" P# A9 ]+ T0 z8 u/ s, J* Q
                        {       3 u- }9 ?) a' u

+ c  G+ N( U9 g, s$ o8 I                                // 重新载入贴图,顺便说一句,类似功能的函数还有
& I" L+ W! z  a) k& x  ?5 h4 J  k$ C9 ]3 M# P( S$ I8 }
                                //virtual void  blitToTexture (const Image &src, unsigned uStartX, unsigned uStartY)=0
4 U6 C+ ^2 I/ Y  _0 D; J4 v4 n: x( B8 d5 q* n  W7 D- g
                                //和virtual void  blitImage (const Image &src, const Image::Rect imgRect, const Image::Rect texRect)5 k0 B5 n( `5 v; b
3 z, M7 j7 K/ L  v2 `5 A, W
                                //不过blitToTexture()在ogre-win32-v0-14-0之前没有实现,没有尝试使用。 blitImage()就算到现在也没有实现。 : O9 i/ t6 ]0 j7 S# ~* l' l4 X' }( J

3 g, @3 B( h3 O    ?6 `% a9 K6 w+ z3 P0 [

: ^+ G  q6 ]$ O5 _3 Y% J                                TextureManager::getSingleton().unload ( mName + "Texture");
2 |/ t  W$ Z% O7 t5 e& T% D9 O% h2 _2 q- P" h1 ~
                                TextureManager::getSingleton().loadRawData ( mName + "Texture" , mTTFMsg->imgchunk,512, 512,PF_A8R8G8B8, TEX_TYPE_2D, 0  );
2 ^0 d1 N, f8 ^+ Z; G3 N, ~: l, t) h# C! C* ]& p
                                mTTFMsg->dirty=false;6 X2 k. l: Z( P0 o' d
8 V( r( }% c  A. s7 f! ]6 N& ~
                        }+ U* j1 Q' x" |/ m4 ?* L
6 e& u  ~$ C, G5 r# i
                }
3 c4 u. {; M9 V4 r  n3 ]. h2 v. W: ^# x
  9 W$ ?; q) M7 r+ T5 K0 ~  t( u) B: U

, w# [2 Z/ t4 B         在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。 $ g4 f0 K0 z8 ?$ |" c# L/ t

' L0 L% J2 e4 e$ |8 j  
* o6 |+ |$ E1 y" _% }
0 x6 Y0 `8 X6 L4 v( N7 ~7 @  
( E7 Z; H5 A: j, M
. _: ^2 g# J5 p8 U0 N9 e1 n' q4.结果。 5 l0 w! E! A, \% M3 ~9 s

1 l$ z* l% ]4 V5 _        好长阿,写了好长。虽然多是代码,但写注释也很累啊。重温了这些天的工作结果。就像上一篇一样“在OpenGL和DX9.0中成功的支持了中文,但是DX7.0中竟然出现了运行错误,具体问题还不清楚,还望各位高手指教。”。不过本来OGRE就不怎么支持DX7的,不管了吧。OpenGL中渲染的比DX9.0清晰,是我的显卡的原因么?以上的winXp+vs2003.net+艾尔沙980se通过~。。
- \! K' `6 A9 Q! Y* u9 {! d9 ^: y. g2 X- S7 U0 D, ]- S
        顺便说两句,上次发表了拙作,没想到好多朋友和高人们找到了我。甚至联系到了一个南方的公司,说要做一个引擎支持中文的方面。但是卖完400多的火车票之后竟然因为住房问题作废了,5555,退票少了80元啊。还是自己差阿,如果再多学点可能就能要我了把~。努力吧,争取写《让OGRE支持中文》三部曲。
- o  a, N1 \; H/ b2 H5 |  q# D) x  N& ^3 v- _6 ^
        下一篇应该是《可以输入中文了》。
) \5 M3 K! R4 f6 |% U
# B: Q  s- n! l( E8 f. P        也可能写不出来的~~~~~~~~~~~~~~~~~~~~   
4 H; l5 ?0 t: Y5 [5 s( a9 U1 z" D8 V, {; Q
    相关文件
3 ?0 [7 c1 |3 \5 F. D
! X* W/ o) e; w; `$ U    chinese.fontdef//字体信息文件 放在资源文件加中
* V. U% f6 l5 I& B# p6 z4 Z! G! v6 g; M! u
    font.png//字体图片 放在资源文件加中
. |0 I* M* I; T5 P; T# f* G
$ `  p8 h% Q; B) H  
; N- s, H+ G; `# X1 \0 u% P, x% w9 C7 ]' n
    OgreFont.cpp
, h6 w7 U3 d: \" {! i) J1 k4 [* O# L0 y& j4 L$ q
    OgreFont.h, W+ t) ?- d9 N. ~4 t3 ]. j: C! b1 v
; S4 k& A% `4 _
    OgreFontManager.cpp7 w! p+ r- z- a4 H, V: k* b+ R0 N
' `  Z" x1 ?) R
    OgreTextAreaGuiElement.cpp
0 @, ~/ ^# o; `8 g- R! n4 h7 F  k4 u
    //上面文件覆盖同名文件 就可以 先备份 $ H! s+ A4 W9 U' q1 S
) U* C: S& o1 P% p
   / q- t) V* |/ w, S: ^7 W% R- p

3 y9 v8 {' c$ f/ c( I5 ~   solo5.ttf//这个是一个中文ttf 我直接替换了原来的ttf
7 K9 f8 H6 Q% H* M& J. y1 u6 Q8 V. p8 m" B0 ~" |. R; }
   unicodemap.h//这个重要,是换算unicode码的数组(文中提到)
. F) a: Z& D: l5 k5 ]
7 h; p/ m! T8 O3 |  / a8 |* {8 q8 X& L) ~
2 L' d1 S! h# x2 y5 L
这个是在ogre-win32-v0-14-0基础上改的(上次是ogre-win32-v0-13-1),
3 f; c' U$ A: h; R8 _- C# C) S8 [; F5 |
请到http://sourceforge.net/projects/ogre/下载
, G1 ~. ?; Z0 h+ ]% n6 i! ?& k5 e0 b( B  K6 |8 ?: ~1 @
配套档案下载:http://www.gameres.com/Articles/ ... /ttf.files/file.rar
2 D* n- d4 a/ }$ c& }) I! \3 D. [" w
免费打工仔QQ:1850070
8 t) C. T7 l3 W- Z6 s+ v$ G) u0 R- C- F" u6 m
From: GameRes ! j" \. w% m0 E, F1 b) W3 j4 P" D

$ s8 L$ |* ^: O/ {7 E; z) i5 Chttp://www.gameres.com
! t& N7 w( p4 u4 k: k
' D% Q* X+ J4 \5 n上面图中“免费打工仔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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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