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

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

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

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

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

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

开源的图形渲染引擎OGRE(3) --让OGRE支持中文TTF字体. R1 S$ O* c# x2 i

: r* M6 [9 l; `+ D0.还是前言
- @4 F# i3 Y/ J" r; I% N3 S0 w- O
        如果你希望能看懂这篇文章,请先确定你已经看到了《让OGRE支持中文》(http://www.gameres.com/Articles/Program/Visual/3D/OgreSupChn.htm),因为本文是在上一篇文章的基础上写的,并且假设文件都已经按照上一篇文章进行了手术。但是如果你只想简单的使用TTF字体,只要下载本文附带的文件,重新编译就可以了。 ! h8 N4 A" j7 H/ G/ b8 h8 K% ~3 G7 a

1 P$ }) H7 m) i. b. Y/ z1.检讨
! n" M1 H& |! s& K
: Y4 L$ F8 A& b. g, s) S        正如上回说的,我们已经实现了一个位图的字体。但是当冷静下来思考时,就能发现这种方法的诸多缺陷。读入一个2048*2048的位图,等于在显存中保存一个2048*2048的贴图,不说是否所有显卡都支持这么大的贴图,单是每个Font字体类吃显存的胃口,就足以令人心惊肉跳。如果定义足够多的字体类,我想你的游戏的配置要求,在某些方面足以超过《DOOM3》了。 4 w  Y- l0 X9 y; I& r* g# S9 b
; U  I8 d" t0 @8 R! \# `2 Z; A
        而且这并不是唯一的缺陷,文字大小相对于位图大小比例相差太大,导致浮点数的文字位置误差很大,你可以在一个文字旁边看到其他文字的影子。(虽然可以通过增加文字间距来解决。)还有点阵字体本身的缺陷,就是字形单一,不适合放大缩小,一些文字边缘的马赛克,足以熄灭任何玩家的投入感。
* P# O; q1 m$ a% k: g- b( i, [) f" I9 B$ A9 @. L7 y
        似乎TTF是唯一的解决之道。 6 C7 ^3 ?. q3 h2 W# E

6 _  u, Z6 y( {2.基本知识 & ?+ q, X( R1 R; L

2 z0 j. c( c$ U(1)TTF字体。
, x: w) O& a4 _5 p
1 Y# E  D$ m# L9 T" M7 J        TTF是一种矢量字库。我们经常可以听到矢量这个词,像是FLASH中的矢量图形,在100*100分辨率下制作的flash,就算它放大为全屏,显示出的画面也不会出现马赛克。所谓矢量,其实说白了就是用点和线来描述图形,这样,在图形需要放大的时候,只要把所有这个图形的点和线放大相应的倍数就可以了。而且,在网站上有很多的TTF字库可以下载,或者你可以去买一些专门的字库光盘。然后在你发行你精心制作的游戏时,可以顺便捎上这些后缀为.ttf的文件就行了。包括Quake这样的惊世之作,也都是用的TTF字库。
3 R$ z* {' j5 d! A- u2 l$ i
# d0 P/ g, B0 r! q# w/ A9 b(2)FreeType2库
, k. c3 M; |$ k9 i* v1 v
  z% u  {( Z0 S, ^        在http://www.freetype.org,有一个FreeType的免费库,而且是OpenSource的。它目前有2个版本:1.0和2.0。其区别在于,1.0只能读取TTF格式的,而2.0支持更多的文件格式,在使用它之前请详细阅读所要遵循的Licence,以下是摘自FreeType2.0对字库的支持列表: - \% B$ C& ^  R4 U% t" k
0 C8 _4 x9 S3 {( p. T$ v  A
        TrueType fonts (and collections) 7 x; Y  [  ]& B
: L8 N  f2 L/ n  `4 p
        Type 1 fonts
2 M9 K6 A/ o2 Q" h7 b& H. G0 u0 A: a  K8 {
        CID-keyed Type 1 fonts
6 x, p& E$ [: c6 J2 C- |8 A+ L1 y# Z1 Q% e
        CFF fonts $ p% b# w# a) C

; V. b8 G' w' M; `1 ?6 ^6 N  R        OpenType fonts (both TrueType and CFF variants) ! G1 R7 o" O) Y. Q2 }1 y/ U6 P

! W& o9 v' ?9 h        SFNT-based bitmap fonts
+ z% I! @! ]" p" k6 T+ W/ K1 c. y) e% @5 ?; [5 v8 K! O
        X11 PCF fonts . P' q9 w0 b) h0 d; }! B

# W' U- R; `4 i% ]- ]; m, _        Windows FNT fonts ) b* }2 I. h  r. A0 M: {; z6 k

6 _0 t3 s) f+ |$ A1 t. t" d% `  H(3)“主体思想” 0 O9 l' M* K0 T6 y  e

/ W- w+ u- i0 \  U& _8 U        请参照炎龙工作室的《游戏中汉字显示的实现与技巧》这篇文章,可惜使用的是Windows API,作者千里马肝,上网上搜一下吧。
5 o2 |  t4 h& [$ G% g4 _* ~! w0 {& H$ d
" `! O6 q% r# F, q        附带说一句,上面两条都是直接从这文章中剪切下来的,>_<  不要骂我啊,不知道算不算侵权呢。
' W5 O& r6 i" |& p! [
' B3 {+ U2 K; Z- a3.动手术---比你想象的要麻烦
( i  n6 U! k6 P(1)
: C6 L+ }# D: t9 ~        首先要告诉字体类,我们下一次渲染需要哪些字。以便字体类可以在需要的时候释放不使用的字体。 # D7 G- l5 B' N2 y$ C1 V. \
; ?4 L2 t. c1 L/ i! d
        在Font类中~
6 ~, w2 j8 p7 f  n6 ^, y
' b2 b* r1 t; A$ s8 {/ J9 [3 A        a.增加数据 bool mUsing[OGRE_NUM_GLYPHS]; 用来标记文字是否使用。 2 ]- H$ z' f1 r
7 R: ]/ N; }, e4 t: n
        b.增加函数 % i$ q/ i" |, A2 L" |$ A; B
% o2 e0 H* ]# T6 M. ^: f/ D, D/ t
                inline void setUsing(std::vector<unsigned long>& caption)
8 k( C2 m* J6 _& K4 z2 h& d( m- O1 ]9 q; N5 s* M
                {9 ]# B" G: @, ]3 G1 v
# ?  i, f* ]; B. x, M
                        memset(this->mUsing,0,sizeof(this->mUsing));
+ a8 P& B; M* ]. w+ a6 e
/ d3 r+ T" V5 d+ H' V" h4 ^0 C                        std::vector<unsigned long>::iterator it;$ l  `: m6 V$ ~; I4 d$ n
/ |. G  I- C7 X, m0 Q6 d9 t
                        for(it=caption.begin();it!=caption.end();++it): H) Y$ n! Z5 B/ E. z

( D3 _0 X( S8 U( L: G0 M                        {
; D; L. z8 k  h- x5 k/ k* I
9 g9 r) k2 i" d' A  c- C  b                                if(OGRE_GLYPH_INDEX(*it)<OGRE_NUM_GLYPHS)8 |4 t& J2 K1 t, b# C8 v7 ?
7 |4 e. o6 {% P& L
                                this->mUsing[OGRE_GLYPH_INDEX(*it)]=1;//标记文字为使用
* P! l7 D5 b2 R, ?1 z3 O/ m8 R0 g3 }7 ]+ m
                        }
) ?1 F; H) n; b6 g4 m% O  y! w
                }
% P. ~+ D6 z- ~) _, Y* M8 `8 Z& s* u" ^. y
        并在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。 9 x  u# f# Q: W" l  L
(2)
8 y* W# A7 B: G9 p9 U! _6 ~
' U7 t  x# v; P6 s( [6 a        然后是修改void Font::createTextureFromFont(void);, X5 N! U7 ?- r0 p! B
, {$ T+ J- v$ Y! q+ {8 ?& i7 z
        Font类是通过void Font::createTextureFromFont(void)来把通过FreeType2分析好的英文字画在一个2^n*2^n的贴图上,然后再保存英文字的位置。
5 h4 L7 h  O) A1 Y: K7 k5 U
* f6 p" R$ g$ z- C4 ~        我们需要修改的是: . @/ ?4 W9 ]  o2 _8 W* s' ^4 d; M
) ^" ~, [  o! \# p! L) v) t
        a.从函数中分离并保存画字的FreeType2和辅助变量。我们通过一个类来保存和处理这些变量。
% F5 g  w1 t- l3 D# V$ x$ K% E# G7 v
        class TTFMsg2 F2 a! z& v( p) P) M' G

7 e  p3 g: P& G& _0 h& T. o                {
9 H; M7 g' q2 M- y3 K$ x7 z# E4 {0 ]1 a% g* }
                        class Max//类中类,用来保存几个"最大",# c+ B: M; O# Y" s7 h6 f

- |1 }+ @3 w- ~0 p, F* E8 |                        {
! a. y+ v* H8 F7 B' S' q
7 J& ]+ a4 q' {, c                                int nothing;//这个是用来占位的,没意义,反正没他就运行出错,可能和数据对齐有关吧。 8 N$ w8 Y* h. f: ?$ q& |

  T( A& }/ ~8 `* r$ m                        public:
& s: M1 z4 A. e- ]( u# T. a) L1 Z                                int height;//文字最大高度 4 m# S* \- V4 U" x" J- C* S5 C3 ~
                                int width;//最大宽度
4 T# p6 v- I. s1 W: \% r                                int bear;//最大空隙?
4 |7 N0 q( N. f6 D                        };, @( l2 n9 i; m' c. ?
                public:- I6 B& {7 c. N! E5 G
                        FT_Library ftLibrary;//FreeType2用
: X' i- h7 ^7 O) @                        FT_Face face;//FreeType2接口?
- d/ |# G1 V* d8 t! b3 R                        uint char_spacer;//文字空隙
" V& G* V" n5 W                        SDDataChunk ttfchunk;//数据块,用来保存ttf信息
1 j" p  v& D  C# b7 a; r; V                        FT_F26Dot6 ftSize;//FreeType2字体大小 ( w: |9 H0 R! @7 d. T, f# x# {5 O
                        std::pair<uint,uint> point;//在位图上画字的点 : m. V( D: j5 f. j. ]* z( |
                        SDDataChunk imgchunk;//数据块,用来保存位图信息 / G% L6 U5 R" m6 D
                        bool dirty;//标记,看是否需要更新贴图
, v5 e: s, y1 R) t) }6 u, c                        Max max;//几个最大 ; N3 L; w- A7 {$ I3 ~
, H- ~( M  g8 F! |# ~
                        inline bool init(Font*  font) //这个是初始化函数在void Font::createTextureFromFont(void);中调用.9 b- X  ]. O. z' P

( L& Z" s, u: T; w0 A$ d, M# w                        {       / ?7 R# B. _! `# h9 H$ X) }# f

3 v7 x- H/ v6 d2 F: |: m7 x                                //以下都是初始化,大部分都是从void Font::createTextureFromFont(void);移植过来的 0 P/ r' v7 v, f3 i$ d

6 I( d( b& S" t: C8 E5 t2 H                                dirty=false;) W6 m) {6 l: \

8 N4 `% P1 Z1 ]% A* l$ L                                if( FT_Init_FreeType( &ftLibrary ) )
2 Z! y3 \/ h9 b. T- |5 _
# h% R. P/ a, \* g, [' n5 p" P1 v& z                                  Except( Exception::ERR_INTERNAL_ERROR, "Could not init FreeType library!",
. p% X1 _( w- v, U
2 x+ y6 C1 [5 `4 F/ F7 |                                "Font::Font");
0 t2 B* j9 l' ]: b/ K- [. R& G8 ^6 M( L, ^* i* o" z1 z, R
                / H9 b% \5 s6 x: B# d- Q3 l$ f' ]( u
( T! k8 H3 {, X( b' @: j# K
                                char_spacer= 5;
! Q1 V5 {9 w2 w; k  E" D
6 |: M+ G$ _' f. c                                FontManager::getSingleton()._findResourceData(font->mSource,ttfchunk);
' b& A9 _. d2 Z% o( p4 N/ v
! t) m9 n, [2 d, {0 i* J  s                                if( FT_New_Memory_Face( ftLibrary, ttfchunk.getPtr(), (FT_Long)ttfchunk.getSize() , 0, &face ) )
+ a1 K' b4 W/ _9 ^- _* m2 F) a# C% a5 `- i( v0 X* @8 Y
                                         Except( Exception::ERR_INTERNAL_ERROR,
) V  c8 [3 e9 @; K. B
; a& N$ y% v9 a                                        "Could not open font face!", "Font::createTextureFromFont" );
0 ~3 H. R9 f& Q% ~9 l, e0 K3 V; f( ~  g# x
                                ftSize = (FT_F26Dot6)(font->mTtfSize * (1 << 6));  G5 t% ]! t! N" n6 f/ C+ b: [
% }% M0 ~$ X. R- Y& B8 A+ S* v  |, Q, R
                                if( FT_Set_Char_Size( face, ftSize, 0, font->mTtfResolution, 0 ) )
: ~9 e2 c8 F8 |4 ~/ ?+ y, u; D% Q: w
                                        Except( Exception::ERR_INTERNAL_ERROR, * b' P. N% M2 F8 a: Q, G

( ]4 H1 D0 S# D6 b# g; J, i- g                                        "Could not set char size!", "Font::createTextureFromFont" );- p' R6 z. X! n
2 h3 B+ O9 F# l. `! J# K! v# v
  6 A, \2 `0 N0 @4 k2 d

1 I% N) y  ?  Y) y                                return true;$ F2 g0 a( f9 X1 V$ A+ J' h
5 s$ k# V% R; J7 G" r$ q! {
                        }! o" w3 c! ^+ J6 s9 N
8 }: _( @1 e1 L; r- H
                        inline bool done()
7 O* c7 o, l8 C( |  _
% D% Y) ?4 a- w6 y4 _- A) c% L3 L                        {
. V4 H) _- z& ~0 G& r# m9 C1 a1 M: ]: ^$ A0 m
                                //在Font的解构函数中调用的,本来应该调用下面两个函数,但是不知道为什么一调用就出错,不用倒没事。 . I; r7 R; b$ q8 K4 D

" ?8 X8 L. w* ~. K5 M' F0 d                                //FT_Done_Face(face);
2 H) Z2 ^9 J( `$ Z0 e' j/ e* w1 R, v7 i: [' P  ~+ r3 A! H% R4 R% }1 \
                                //FT_Done_FreeType(ftLibrary);
  f, o' f# A. j4 N) b; N/ d) \& m& \
                                return true;
% Y% R6 G" s. N) @% D7 F
2 c4 f5 C8 y% R. u. S! g1 C                        }+ Y3 Q  P; Q2 f

9 l& m, C% x: ?+ x, H* _                        inline bool getRect(Image::Rect & rect)//这个函数以后用的,是用来找到可以画字的贴图的空的位置 * r6 a0 B! w3 N8 `: P  \
5 V2 ~/ `3 o- n2 H* t7 W  t: Q
                        {
4 y. K( L9 O/ p( P* u0 |0 E$ E# f4 A4 v. U- C& z4 {2 z7 ?- g
                                if(511<point.second+max.height+char_spacer)
; ~  l# z/ x/ M1 H- p: H- z5 w
8 d: B  A* M( i$ G, D' B& ^8 Y                                {% `) H# U6 V4 d: D3 P# R

) ~5 x# Q9 ^; {                                        rect.right=rect.top=rect.left=rect.bottom=-1;6 a5 Z8 Q; P3 v* [$ ]$ ^$ [) h/ X2 I

: b/ _( K+ c! ]# w" N                                        return false;
2 G+ i4 }, [1 m6 f: f
* ^/ \9 z+ n: E                                }  H4 {! d' [1 |2 u- T5 F

! I0 M& c& o6 j8 ~0 k/ V7 H                                if(511<point.first+max.width+char_spacer)6 l& a1 V) @  G3 i

! J1 Z, o8 c) t* V& k                                {
. U  H$ }) j9 F& |, {8 ?0 X$ ^; y
' y/ {7 ]3 w/ \- w2 ~) E                                       
) ?2 h* F' C: N" L! g; d* }
  Y- i8 e* B  x& V" q/ j                                        point.second+=max.width+char_spacer;
  X% I: ]7 c% W$ k; L2 e* R7 }5 k+ x& w& `
                                        point.first=0;
* E6 O1 e$ |! V1 l2 a- l; b
% p$ o% \2 Y$ [4 s                                        if(511<point.second+max.height+char_spacer)
! m( T& Q5 d/ k0 e2 j+ Y0 _2 U$ ^' H
                                        {2 l  @4 V& p! C. Y2 }# t
2 U" t$ U) L+ ~6 V
                                       
7 S8 b. R% q# F# D5 i. f
" |1 @+ [# ?, b                                                rect.right=rect.top=rect.left=rect.bottom=-1;
3 g& Q. [/ S2 @  H; g+ T. M( j0 q, X! i3 K
                                                return false;
, ~' v& P. H) |. X2 x- Q" i( w0 ~3 a% s5 \  G$ j
                                        }
8 f4 |2 c; c2 b  U7 f. @7 P9 c! ~7 c+ W: S3 _
                                }. E- }& U2 }# a# p, d% P

. r8 a  `+ |$ s                                rect.left=point.first;8 N  _& \. I+ f5 O% b
2 `& g2 L, }' h4 h6 d9 x. ?
                                rect.top=point.second;
: Q8 Y$ T5 |( L8 j
! L7 p# `# Y* T% r& [3 X8 ?. R" a                                rect.bottom=max.height;
' \/ o; F% T/ D" y4 T( t
9 Z: ^8 c; v& K' h& e3 g                                rect.right=max.width;
% W7 i/ M, T7 \: i1 ]2 H) f+ H6 l2 e1 ]  W# ?4 l9 |& J% D. M0 e6 p
                                point.first+=max.width+char_spacer;
. s) I* M3 a( i0 _. K$ P- R* J' r5 i/ ^! p+ x$ ~$ b( |( ?- T( d
                                return true;# i& Z4 T5 c: P' Z9 _' d4 W
- [6 \" I: i8 A
                        }
/ G2 @/ P9 U, C. d# Y. A0 J& l7 ?% {
                };* Y& H. |' }' ]5 O( q1 ]

( @! a. m3 S# _. v" }2 {        上面的类定义在Font类中,在Font中增加 TTFMsg * mTTFMsg 数据,并在构造函数中 mTTFMsg=new TTFMsg;/ Q$ ^& B' [+ ?& I2 {6 {0 B3 r4 ]

4 U; H9 d) ^' z% I( a        ( I  p7 I6 e: [0 D2 K  r
' _- u* q% W3 R" y9 m5 l
        正是修改void Font::createTextureFromFont(void);函数,主要几点,首先是分离出很多变量和构造到TTFMsg类中了,然后是贴图从2^n*2^n变成固定的512*512,为什么要这个数字呢,因为256太小(废话了)。能保证512*512大小的文本区不会出现不够画字的情况(所有英文+符号+没有重复的汉字),这个安全区域基本上是够用的。(什么,你要画满屏幕的汉字?哪你自己看着改吧。)还有一个重要功能是,要找100个汉字,找出最高和最宽和最大空隙作参考。修改完成这个样子了~. [0 r3 h2 N- r! H: W

, b. F7 V' v/ i4 u$ d; Z    void Font::createTextureFromFont(void)3 R0 y, @4 W8 k
& L( _, J. b7 c# y4 L& c/ [
    {
' Z) @" _( C) q! P& H$ v- Q  U8 }( e' W' l" v% A% f6 h
        mTTFMsg->init(this);//初始化FreeType2
3 f* ?% {" M: j, o8 S$ m
9 T! S& L6 s# v        uint i, l, m, n;
) c/ o8 N! Z" R% s& V% `0 i# Z1 A8 W: I( Y" H. p
        int j, k;, O7 w" ?- w- f! s
. d0 g2 A; w- t+ [, P' [+ z$ X
  
3 U1 n. U/ Z% ~% _5 K0 ]* v7 e3 p9 ?# s5 k
      
" j1 p7 L& S, [4 f3 Z8 [! O
) b  p/ |3 F/ [2 }* G        FILE *fo_def = stdout;//啥意思?我看不明白 ( U( ?- `+ Y& S+ P# f
# F0 }' O% R0 H, Z% n7 A3 M0 K3 z
  ( ^) _* f0 Z5 ^" i

: N: h+ [; [1 {2 h1 i, n$ D        int max_height = 0, max_width = 0, max_bear = 0;0 ?) U& T0 b$ x) F* t9 w

5 r; Q/ V0 G. R& A% z  ) k3 s' I$ U: u  A# V

$ D8 l& S, J3 x: E/ l3 Y; h        uint startGlyph = 33;' f( [5 L/ f, ~* u, E8 L
- ^! b4 N5 ~- C0 T  l  z
        uint endGlyph = 167;
0 }/ L8 ~1 O" W) _! S) R6 D# {
% p  [, k( z0 v  
. e" m1 v* J$ a1 b, W1 R
/ `- O! K2 k, n        // 找英文的找出最高和最宽和最大空隙 * N$ n4 j6 N  X# G; r% Y
* J" N* d) b. _7 b1 I$ u
        // Calculate maximum width, height and bearing
6 e+ n& P4 Z$ a- i' j( r3 q$ ^, N+ B7 S' G
        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )6 T$ z$ s5 [% i' u9 i9 F
( Y+ E# _% `0 ^
        {; K8 {# g# Q6 E( H8 E* {

: L- z! H- d7 d) v& R" g            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );
/ f% Z2 o# `! G4 i+ _
7 _4 l6 c6 w1 N' Y  d9 H            //以后的 <<6和>>6都是FreeType2中的数据和我们使用的数据的转换
( u$ e/ \+ M9 W, U: g2 t2 Z9 }% z& c. W  ]
            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )
* X7 A) x% w+ ?; v  H; n7 x% u# N! t, q4 E3 _1 x
                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );
( c! U% q9 ^+ h7 H, B/ s. s
/ M4 I3 K0 Q; r+ ]' a% ]$ Z            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )& K! X5 t2 @+ I, u* a: y
; n5 \$ H% Y- s0 f- e0 d) @
                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;
8 b- |' m+ Y1 Z
2 c- `8 C! L; X! V' Q  C: Z4 c9 b: j6 E  
& d0 g, S' X( R3 I$ F( ~' g0 S& J7 \1 ?& U% u9 \
            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width); J5 P4 [* |! T" H
' ~" m" C) E' z, D9 j* o
                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
5 \7 }6 G, p  ]+ d3 |$ m9 I
% y  x+ p4 g  W* i        }: _: c4 u9 o4 k# U* ^
7 ^' N4 F( t! Y$ p) S) `0 ?7 Y7 h
  
8 |- w  G/ l4 d; K. j  r
% Z* T0 u5 `2 m' g  ' q6 e$ z, o: U% w0 C/ `
+ i8 i& e8 l1 S: n
        //下面的for是找100个汉字,找出最高和最宽和最大空隙作参考。姑且认为最的汉字就在这一百个里了。 , v/ j' }" I, O

3 ]' Z2 V) E/ n) M# B        for( i = 20643, l = 0, m = 0, n = 0; i < 20743; i++ )
# r0 n' O# B; \0 R6 E3 J4 ]3 b. t5 Q
        {
9 ~* b; K8 U) P1 v
8 z& V6 x/ {3 l            FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );5 q5 J1 ?. k; W" S

  M; }9 R9 [, b% l. y  
# ~; Z. a' @. ^; u( _# [5 M/ z* e5 f/ w2 i; C  J/ M! y
            if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )
0 D4 r% V2 Z4 ?" x9 N( a. O2 T* F
                max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );
: F% g7 a* k( m* x) h
9 b; }" [: F, Z0 L8 k* ^4 r            if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )
& I0 d  e0 y: [" i; o, ~0 K9 e/ z, H& a0 H. A+ g. U. b. T
                max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;7 |) p! @/ P6 {0 Z- r/ `

" o# |1 C1 F# d; C" Y- e  
; ?1 A' V! g& E9 b0 O
6 v) l& E. t; ?+ f# U5 b            if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)
6 U+ S; p0 e) D& N3 ~% i% M% Z  K& [$ S1 j9 n+ K, E
                max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
) @0 E4 I3 n) b% q1 _
" v6 a9 T) S9 U3 {  
% ^& v+ v2 U$ Z! X0 w& F. k; ~, z4 n* c$ y5 ~8 h3 L3 N
                        
3 `3 Z% J$ v0 Z3 ~7 N# B3 E
  m, e2 i1 P5 ]6 o            if( (mTTFMsg->face->glyph->advance.x ) + ( mTTFMsg->face->glyph->metrics.horiBearingX ) > mTTFMsg->max.width)
6 e6 n; X9 y! l& e
2 @; L$ D+ \$ ~5 H# u' ]( q# T  i/ |                mTTFMsg->max.width = (mTTFMsg->face->glyph->advance.x  ) + ( mTTFMsg->face->glyph->metrics.horiBearingX );% Q9 G+ a5 ~3 b0 X
  x. A3 X# @; w; _% s
        }
+ q5 H1 d) ?; X3 J  O
8 t) s& H7 C3 [6 v8 C0 W! {  . W' P1 I: T8 Y9 J1 G
! X' w  ]5 J1 `- W. u+ O
                //下面几行行不需要了 我们要512*512
0 ~" k6 e' E! W1 s8 ?+ }& C+ s+ W5 _9 G' W; M7 \' W+ L! n
                size_t tex_side=512;//就是这个了 512
1 F7 X8 ^$ W; n2 i+ `6 i" \2 g7 j- `' e. }9 N! `4 V
        //定义数据宽度 因为是32位的位图 四个char为一个像素,为什么要位这么大呢,难道不能用8位的么,我尝试着改来着,不过改了之后就不透明了。望高手看看能不能改。
0 ~/ [5 P5 `2 t
0 h/ m- z% `" `* n# U- O: N                size_t data_width = tex_side * 4;, \+ ^  i( o5 R" f" @. e+ _

" X6 A3 z7 o' _  
6 o3 @; C# _5 |$ x! w( q* t
' ]( {6 g: u4 m' J, w                LogManager::getSingleton().logMessage("Font " + mName + "using texture size " +
3 ~9 ]0 j$ v9 a* _% r8 ?7 F
9 W  l" ?! v# Y8 \8 w3 b                        StringConverter::toString(tex_side) + "x" + StringConverter::toString(tex_side));
# H, E; E0 C7 S+ F7 @6 I: D4 A: v! G. C: w8 g* u% c9 p4 z
  7 B# ~9 X+ b1 Z& y6 }) Z- G

: t3 v5 ^% V. }0 ^, _        uchar* imageData = new uchar[tex_side * tex_side * 4];//设置一个空间用来保存位图
* H1 F9 x& z1 V- j
8 O( L  c1 J! c8 \$ X1 b                // Reset content, c* U7 j1 ~' B( B* g! a9 B4 K3 f

& |( l/ o6 O5 X7 p                memset(imageData, 0, tex_side * tex_side * 4);//清零 : P" A5 o( }, X* }$ o  s

+ l$ K. S- u! @! V$ |% z2 {  
6 L) S' T) _$ h* C& n1 ^# ]& O7 m( S$ q7 R& M
        for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )//遍历每个字,
' s0 v. F% N+ S+ Q: m8 G* |- Z. e) j4 x" I: ~6 f' V9 I/ z
        {0 S+ X) O7 o6 z: F9 d; M1 w  l2 K) D

% r4 S/ \2 _$ _; O                        " h2 v" }" {1 z2 f

7 X0 j3 \' f0 `$ `4 r% y            FT_Error ftResult;: |& {1 m0 j4 f' h! V! p
' n2 ^0 Q- U/ n0 Z- o- f  D
  : O, @* d8 ~8 i1 m
& O+ u; d, P" F; O! m
            // Load & render glyph
5 f2 j! v" H/ x& V! n' W7 I- m# I
1 U. I$ ~# V. f7 r            ftResult = FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );//读取字体   i. N: F3 C2 m: r% R8 W4 D
$ ~- f0 Q5 k5 n1 w. i1 C
            if (ftResult)
  |) ~4 \9 J8 {. y6 p5 g9 ?
% A4 a9 J/ N* U- G2 c' d$ D            {
3 n$ Y* B8 N9 H
* F  \$ A8 C$ H7 S& ~; M                // problem loading this glyph, continue
# }) n. v0 {0 _. P# Q3 S$ T) M
( b3 V8 d7 K6 y( J2 q1 }. g                LogManager::getSingleton().logMessage("Info: cannot load character " +$ |, m+ g/ W( g
$ q) C7 S; I# c; C( P1 Y
                    StringConverter::toString(i) + " in font " + mName);2 }. @4 Y  E) A4 \! Q- \$ q( J/ k1 Z
4 D$ R4 [5 k: l% R4 i4 ?2 i
                continue;//如果错误跳过 & F1 v* Q; [6 O: N7 o0 b
: k2 ~' }+ i8 l0 v8 H9 j
            }1 e, S- Y7 n; e$ M3 {  \$ B

# R4 \/ A2 _6 M  u" `& g  
0 J. o4 Y% L( v" k) d! j4 w/ Q  y9 u6 f  z8 q
                        // 应该是字宽 . S- t1 n+ C( r7 N

2 H/ T7 d% m; |, r/ F  ~                        FT_Int advance = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );, I* F/ i  r# f% P' k' b, M

! `& _3 e9 s8 ]. m6 [9 g                        % |6 P& k9 R9 r5 j

3 x6 k2 l3 M5 ]* M! h) x                        // 得到FreeType2的位图 9 c: }7 l; a" R" }" U' m
& d  V; O8 A8 k: P  a, Z7 H
            unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;
* M/ N& i/ D. G7 M9 |1 f+ N% {4 d! @7 u2 s$ H' m
  
; O" ~$ u" Q9 v' z$ T
+ q3 _, d% g+ F5 q8 g' T+ o' }            if (!buffer)  [  `% L& w' M9 y
0 o/ n: {  x7 _) V
            {! @3 @: |6 n0 G3 q
  a4 @/ k3 Q, J9 o: i/ I; Q) }+ A
                // Yuck, FT didn't detect this but generated a null pointer! ' ~5 H0 ]; D* C$ f

7 @  C2 t6 L( z                LogManager::getSingleton().logMessage("Info: Freetype returned null for character " +
9 Y$ ~! C5 _+ P
% ~  L- J3 j) I+ z  Q4 R2 Y                    StringConverter::toString(i) + " in font " + mName);6 f( ~0 f  g: |* l) \7 R5 s

4 J, h$ o4 Y% }                continue;//如果得不到跳过 , s& E$ ~( Z: {9 H* J
( L' E, g% N6 P% j2 a, a0 c' ]2 @' k' z
            }/ n/ Z: x9 {8 l0 p7 S

+ k0 Q- _& O+ V; w3 @% f: _: K  
& ^9 }7 l. e5 S8 y0 r2 O! V( f8 L# \+ i4 {& ~# L% E
                        // 得到y的空隙 (最大空-空-本字空)就是说空出这些字底部就平了
+ k+ }1 g0 @6 n7 h
* A6 c  P; F! J7 d/ O            int y_bearnig = ( max_bear >> 6 ) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );
+ Z2 t5 f# k$ ~: M. f5 \9 e: B) H* T) |0 j+ L: O
                        2 s  k0 [) Y1 g7 D7 E6 X; S

; O9 W% W' Q; R6 C/ Z/ D            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )
0 [7 ^/ {( L  q7 a: r7 j' o% n
: j* M+ V% S: W% t, G) r# V            {
; s! `& C2 z$ r+ }0 U; D4 L& a) z  \8 p) o6 J: T  L
                                int row = j + m + y_bearnig;//相对行+本字在位图的总行+空隙 6 B- Q) K2 c' J8 H) [5 V1 [( }

1 {0 o9 p8 }% J/ s# C  N                int col = l;//列 6 M. ^) j7 @4 D
* p: |# X& r8 H# e
                uchar* pDest = &imageData[(row * data_width) + l * 4];//找起点   7 E; b$ I; J. Z- H

- U# c( g% m5 F; X                for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//画图 $ h2 |! y- K" i" J

* A% e3 z( O# z0 z6 t1 a0 w  ~                {
/ G+ y  |+ q% r0 p6 e
2 ~* e+ Y* }: P* O+ y; j% l! H                    if (mAntialiasColour)//看不大懂,难道是灰色字体? % e9 ]' U0 H2 a8 u% I& _4 q9 u' T
0 V* x0 W5 c- w9 C
                    {; r5 D( K; H8 h* Y* {. X

6 W9 X- ^9 J% R' M9 x+ \, D                        // Use the same greyscale pixel for all components RGBA
4 n& X& ]  N/ w4 C  f9 X/ B- Y
                        *pDest++= *buffer;% C1 h" g4 o% [- z' c

+ X! E' I5 X8 \$ M( k5 g                            *pDest++= *buffer;
) ^+ _2 ^6 _+ C" K5 ^9 M! g
  g& V8 k5 q+ P                            *pDest++= *buffer;
# j  ^9 q, c5 i, P, {" |/ c0 H" C8 O) D/ p' i
                    }
4 I/ A6 N5 A- @2 R: a3 c: N+ n0 G+ ?7 Z& e1 n& i7 i
                    else $ ]4 i4 e9 z6 l, [9 Q% W

1 G4 g9 ^' E; g6 Z                    {
1 B7 s; x8 ]" K5 ]8 p3 A
; J% u* y, Y4 @/ o: t- z  x" Y" j                        // Clamp colour to full white or off ( L# O  F. M" I* K
1 j, J# |7 G# G9 e" B' l
                        if (*buffer > 0)0 W1 o/ {7 v) i) \. w
8 I! j" X) R8 r5 q% p- C) l
                        {6 e1 S& e! K% t0 _0 [

) B2 r4 P3 {( ]$ D( n3 {0 J) v                            *pDest++= 0xFF;" A) z2 E) Y" I3 ~5 Z
! |- w9 a5 X. |
                            *pDest++= 0xFF;$ v: a7 }$ j' ^0 y) F7 v

# O, X! H6 F( W                            *pDest++= 0xFF;  ]8 Q5 ?! f, f0 q' f
0 S2 c% @7 P2 h) S
                        }
9 K5 S3 S0 G& X4 w3 n/ Y6 U: P) ^( [8 m' D3 d
                        else , u- l3 k; g5 B) D  \7 `: U
# I6 v$ J1 T+ r- r( J
                        {
+ e& K8 V! Z/ Z3 i  A8 Q! \+ ?* q) P- _6 I: J( @  D5 S
                            *pDest++= 0;
4 Z* |* {; a( f* o8 R$ i! t
: E: I0 S$ @4 j7 M1 P- E* {) c                            *pDest++= 0;0 p5 {/ @% Y: |) u& ^, k
& Z: |. ~7 T7 s5 _1 |
                            *pDest++= 0;8 @! K- R& V- P' f( V8 K0 m1 J
6 g3 s) \2 ^3 r" u1 \  J* u, g
                        }9 D( e8 E$ g6 O( A9 _
' U/ e& Z3 w. M& [, `  A
                    }3 D2 r. o. q" t4 ]3 w

! g* B# n7 j, s+ Z9 h! V9 K! d4 O                    // Always use the greyscale value for alpha
# u: a  v& ?9 f
" i4 A9 T- D  N                                        ( ^3 q  A$ o( ^' z; H$ ]5 @

4 y# w$ T) k" d  m6 k' O/ p# h                    *pDest++= *buffer++;//alpha! 我是一点不了解了为什么是这个?
) A. p8 R7 g9 l  X' a: J. h- c/ x4 ^4 I& _( O
                }
# g1 i- L' a* F7 R7 z$ \5 \6 ?8 I* J& O3 T# t+ ~  c. K
            }
! c$ J5 A" J5 N2 I- E  i* o
/ E( D! d/ \* W5 N7 H" `7 t2 c4 `3 x  
* d0 D8 n: M& N3 {3 N  Y
* ~; F- k# \3 {: ]1 ?# s+ X+ a            this->setGlyphTexCoords( i, 2 q1 }# b* m. r( |
& f8 u1 S" N0 ]" f
                (Real)l / (Real)tex_side,  // u1
" c1 H9 B9 m* j8 P" s. d- z: w6 H
" D4 V& g% h' Z" O$ {4 k2 K                (Real)m / (Real)tex_side,  // v1
, C% X8 _! u6 l% e/ n
" u+ I% q! e1 @6 U7 s  d/ ^/ N                (Real)( l + ( mTTFMsg->face->glyph->advance.x >> 6 ) ) / (Real)tex_side, // u2
1 z* j% F& B. B0 W! a. I
1 C8 Z) o; N* o- p- n: {9 {4 D                (Real)( m + ( max_height >> 6 ) ) / (Real)tex_side // v2
) L) W1 m. _% u, `- B; L2 o2 d2 c% N: V: K& \3 }
                );//设置坐标 7 C/ Y0 I6 d6 f2 h& m" b$ M

( U& z; {) s7 E* }7 ?" g  7 z* j6 r" x4 h9 }5 Q% ^" S
5 n, n1 q+ g- G
            // Advance a column - V- b* N4 e1 K

, `$ Z, Q1 U( i! w4 ^            l += (advance + mTTFMsg->char_spacer);' G6 k5 m0 b. x+ q. j
" {$ G1 [/ j& V) e2 I8 E8 Q& E6 q: H
                        //l+= 本字宽+字空 4 E/ o4 u6 C. Y: I/ h9 x: `9 O8 O* {/ t0 s
6 s# Y/ ?# @5 |; s
  % Y* y/ g  Q3 T/ P1 H. v3 @; F

6 @/ K4 j- E8 x1 L            // If at end of row
: O' [: ?' D3 o& a7 S3 O' v* C% {! L+ \6 N2 [( F7 n8 V  ~
                        //如果到头容不下一个字 # f+ _& b/ I6 [6 m8 f5 x2 n6 h0 ]5 |

9 O+ K0 @) R; o$ f8 t            if( tex_side - 1 < l + ( advance ) )# A& y/ H2 t7 ~3 q* j# C' T
- S4 v3 K$ P* D
            {1 B% z6 v0 r1 \2 t% x

" G; J2 v( x  Z* K0 V1 J, y                m += ( max_height >> 6 ) + mTTFMsg->char_spacer;
" T" @1 Z, z* e5 R! i8 a4 [* A' R) _% ~9 w: j
                l = n = 0;# l2 N- a( F. L/ }( D% Z6 U, P' N
, _$ x: u# P3 I* \- c( u8 Q
            }
5 j0 w& _, T& K" I& O* ^* H5 v
& `+ l: g+ N8 V0 F  4 h  t1 Q$ s0 a8 o

, ]. M( @/ o' o% R, w        }
$ p# R0 Y8 M; ]9 z( }! S* I! x' u) s3 \- N  i
                // 把信息存到我们的mTTFMsg中 >_<
% o. I  V7 y$ M" K# k2 y1 w3 N. m3 ~  Q0 d
                if(l); M: a7 ]- c$ n

  s8 N: Y, Z! S- O                        mTTFMsg->point.second = m + ( max_height >> 6 ) + mTTFMsg->char_spacer;
* @( h: v& ~$ f
! ~, ?- J9 r0 y5 X                else
& r- [2 A! W; Q" f" q6 S; \. x9 I
  c/ k+ e7 y' i' O  u  X                        mTTFMsg->point.second = m;
% d; W' S0 F! ^/ X$ o. T3 v6 {/ U$ a) t5 x# n" D' `, C
  
% X7 C. m# J; ]! R( n* g  i  w" l9 ?
                mTTFMsg->point.first = 0;//另起一行
  @: @) q6 `0 P" j
: i, z! P/ h, m  8 b8 L1 L9 j( `, O
" m5 L; i  R$ a6 r2 \; n3 l& q
                //下面是保存几个最大。 . {3 C4 z, q! x( r0 c+ s
" y4 z0 z# n( N6 [) h
                mTTFMsg->max.height = max_height >> 6;
! k. i$ @! ?4 q( J) f
/ z3 e7 f) ^7 V& u/ e. u                mTTFMsg->max.bear=max_bear >> 6;7 o# c$ Q# X: q% z- G; H. `

) V" s2 f( I* ^# d9 n                mTTFMsg->max.width=max_width;8 E9 ^- R! u  t# i5 T% \
7 o! |6 G7 v$ d& a7 ]4 |
  " ?$ m7 Z& S( V0 U

# Z3 ~3 K( I* m' M5 e                mTTFMsg->imgchunk.allocate( tex_side * tex_side * 4,imageData);) e% s; w/ R* a8 _6 t
$ k! m! H0 J; S, B4 b8 e
                1 @4 f& ?% B# f- y  ~

/ d/ E0 w9 u$ K- R  B( X                //不知道为什么要设置img这个中间变量,似乎可以直接从chunk创建贴图
0 v' X( v" C. R) P* D" z' c
: K; d- t& e' h9 r8 \        //--Image img; 6 `/ q3 p6 g' ~1 |
3 o& U5 o4 ?! J1 z& d" D, d
                //img.loadRawData( imgchunk, tex_side, tex_side, PF_A8R8G8B8 );6 U' c' A% A% f+ G! k
2 h+ W2 a( |& [4 G
  
0 J( u; A6 Q7 h- b7 v' f* O: o4 u; Z0 B
                //贴图名 . J+ C! i. a8 C7 K& T
# e  M) ~0 C% N% f; m: a* F2 J' ]; J, T
        String texName = mName + "Texture";7 C5 q! h6 ^) M- |* U6 u
( I/ q% n9 l2 `' q% @7 _% c& L
                // Load texture with no mipmaps
- }  {: f5 Y& F. M! C, P+ T% B$ Z2 k; m" ~' e
        // 把从img创建位图改成直接从chunk创建贴图
) p1 p* Y; p; [, z7 @0 |+ I8 X
) o& ]8 ]' n+ K/ M% C                //TextureManager::getSingleton().loadImage( texName , img, TEX_TYPE_2D, 0  );
% ~% y- U) p, t3 P: h" i1 U' L8 @! P* z& ~1 P
                TextureManager::getSingleton().loadRawData ( texName , mTTFMsg->imgchunk,tex_side, tex_side,PF_A8R8G8B8, TEX_TYPE_2D, 0  );
. X& a+ {& d# I
2 q( r: i4 g. T        TextureUnitState* t = mpMaterial->getTechnique(0)->getPass(0)->createTextureUnitState( texName );
" c4 \. Q$ a6 Y1 z& ]
3 T/ W# d3 L5 Q  C: o+ q; }( h                // Allow min/mag filter, but no mip 4 z. M; ~6 m+ D3 c0 w
8 O, v! b) u% Y3 r. J, g
                t->setTextureFiltering(FO_LINEAR, FO_LINEAR, FO_NONE);+ V% a  L* j2 M' D/ C

# Y- T& G; f/ O  R8 k8 @* _        // SDDatachunk will delete imageData
& w/ \' b9 x* ^" P  ^" ?! A8 Y' g; W0 f( k9 i5 Q
        : A! O* N, I+ {1 T3 y

8 `: A5 e: [! Y" |/ G# J    }3 m7 {5 m$ I& j! ]1 ]2 ~
0 g! e- V1 q3 {" R' n
        你应该对照一下以前的函数,改了很多的。 * p) ?. p0 F- N% X1 s3 {, c
5 _$ ]. X5 E7 S; M2 Y* i; ]* L
  . @+ Q/ G3 _# J6 E1 Z% Q

5 a* Y( c. @2 T( q& Z  
/ g" d' c. M& X2 ~5 Z. T
4 u) s' S+ p# H$ A# B' w: ~(3)
/ _7 d; y+ L1 f3 d4 f
, o; s. C# \5 M( |0 W        然后最重要的是动态的申请和画字。
* b" r& V: j* X8 p% i7 \
! X6 S/ @! l9 W; l# z        首先最重要的是我们要一个方法得到汉字的unicode码,我们用到了unicodeMap数组,提供了区位码到unicode码的转换工作,等一下提供这个表给你,好不容易从网上找到的阿,可惜这个表没有中文标点的对应,如果希望支持中文标点,就要努力找到unicode码并加进这个表了。这个表是这样的 char c[3]="邸";unicodeMap[94*(c[0]-0xa0-1)+c[1]-0xa0-1];就得到邸的unicode码,不知道为什么没有5165~5169的unicode码,是轮空么?
5 l$ R3 l. C# z/ ~
; A; [! f0 Z( y6 Y, F        7 m+ k; U2 p, O, q2 p* `
% x$ U" u2 T0 z( O2 R
        申请渲染(字)
; _0 T: k! Y2 v6 v/ C- a- a/ [1 S: @3 N/ H0 g& S' ]
        {5 E, R! [% x3 F" [

' k$ W3 J. C& x% W* A( f. _* v                if(有这个字)9 A3 {7 R4 ~3 e/ U: c5 w. r6 I

  f: B1 Z1 E( t# {4 |                        返回位置
! ]2 H% ^/ i; N$ y/ d
4 r2 d* j& o4 O4 y; R$ m, U                else& A$ K$ Y3 Y( H7 t2 p$ T

9 z. f  y( z( n& F- P1 s  _1 i                {
# E. ^: x- y' q  A" c& M( j/ {3 s1 c6 Z5 d# M' B
                        if(有空间)0 D+ k1 ?4 P$ p$ v7 ^! O0 ~. x( v3 v
$ ]$ F) a% Y; O: K! ~9 N4 x: f/ ?
                                画字 / ^$ I3 m. J* t, }% H/ P
8 f, c3 M9 D/ ~( M
                        else1 S3 N* K0 a5 L& b$ p& u; ?
) d9 d# u! p, b' f( P
                            找不用的字//找不到就出错,没地方画了 # H6 m; T" ]! v6 }! Q+ y
* |3 Y7 s( V( H) A; c% P
                                删除 在这个位置上画字 " E4 O# v8 i( i% c% {
" E6 q3 L6 _+ t# {9 h, ^1 D7 }9 e
                返回位置
! W$ d% k$ K1 @! j
- i6 M( f+ n4 ^8 \                }0 w% q8 U# {, C( i% p
$ \% z2 z/ \  H) d  I
        }' V$ i+ H! q& N
7 E6 P, l8 d. M/ i0 l
        上面很直观把,大体就这个意思了,申请渲染的函数是inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )  const。去掉const改一改。得到
/ F. r: E3 v) ^4 T4 |9 g( o+ h! h- `5 {4 r6 R0 K! Q1 ?8 v0 W
        a.申请渲染
: t# D8 j4 K- q$ z% t: b+ u- j  Z6 L
- a7 c$ F. _. Q! C7 e& L        inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 )         
2 w/ T& H' g/ S/ P; A
1 L1 I9 J! W4 t" e# y        {
  f* A4 o: a: K0 S0 K, v0 p/ C$ Z- P) D  Z, D
                unsigned long idx = OGRE_GLYPH_INDEX(id);
0 _; f' [' k6 k! l- Q; Z* Q$ T' Z7 P% e/ x4 I( F
                if(this->mType==FT_TRUETYPE)//ttf?
; x" t/ v6 e  i6 C4 L1 i2 A. |: b
                if(id>=161&&idx<OGRE_NUM_GLYPHS)//汉字?
# U) J2 C; S/ a7 o- e
$ k) V3 S- {! N: R& P                        if(!mTexCoords_v2[ idx ])//没有?
5 f& ]+ H3 A* N4 C  W; z% M% C4 W% D0 O: k( H2 {
                                setChar(id);//画字去 ! j  |6 Q4 [% Q! U2 R
- b6 z+ p( U4 R8 ?  o
             3 ^; \: _! I( `2 M9 j7 t( H

8 c( Q9 Q+ A. Q, ^3 {3 D            u1 = mTexCoords_u1[ idx ];& I" R! z* i" c  O6 n8 p

7 ~' `% y. N0 I  ]: \8 k( Z            v1 = mTexCoords_v1[ idx ];* V6 v, {5 \& o; r/ l

9 x5 v8 ~+ s* h" ~' `( B2 W            u2 = mTexCoords_u2[ idx ];( j4 B/ n+ H0 C" z! e9 P

0 V# t. @& G( e7 q, Y            v2 = mTexCoords_v2[ idx ];
( W% m  h' `$ E7 f3 s# G) {$ _$ x
        }7 A9 `6 T$ g# F* ~9 x! V# b9 ^2 B

! P, j; f8 y2 j$ ?7 d2 Y        b.画字等
/ j- W, F% M) d& A
/ U) d7 y9 S+ l! k        bool Font::setChar(unsigned long dwChar)
$ n7 Y: C! e6 X/ K$ a# [6 s3 e) g- T! M$ L
        {* ?8 Y8 z' g5 O1 O% \) \' n, F

& X9 j0 C$ i$ K0 S& U) t( |! \                int j,k;$ u$ g2 R6 R, e

9 q& Z" J' X! p( L3 j# R/ g                uchar* pDest;//操作数据的指针 ; a4 t; @( y) j- `

9 ~* k# _2 h# u' |; L4 {& f                mProportion=0.8;//不知为什么,总觉得中文都太扁平了,所以设置这个参数,在《让OGRE支持中文》中创造的参数 + E' V9 R) |8 B( N( V* [' Q

7 I2 E6 R7 e1 s2 }/ x                Image::Rect  rect;//画字的位置
1 W% R+ O# i! }$ b$ b
3 F% x! T5 B$ b. E$ {                if(!mTTFMsg->getRect(rect)/*回头看看这个函数吧*/)//如果得不到空位置   y3 J: k* R3 K
* n9 O6 j% D9 J; Y% h0 p
                {3 S# X! z, U9 H' G$ L
6 M8 ]) X+ V( u  x9 Q/ K
                        for(int i=161;i<OGRE_NUM_GLYPHS;++i)//寻找不用的字 - z8 M" _% s3 }' @' s# Z9 g
1 D& A9 C! x8 Z% D) y  _& ], @
                        {4 @/ H0 J2 e, G0 z

) g9 v% f: ?; R" [: d+ U3 }                                if(!mUsing&&mTexCoords_v2)
: q1 l0 k* T  V0 {7 z% y: Z% i% N5 C+ W, z2 _  d: w
                                {
+ |% J& J9 C& k4 D. a3 P" N- }! M% y& u% q
                                        // 得到坐标 2 v; P5 d" b: N3 B
+ G$ ?/ A" K4 o* {6 R8 X/ U
                                        rect.left=mTexCoords_u1*512;
& D6 V+ c; o/ L5 E; h2 B/ F; Z# p0 z: `$ S* ~4 H# p, L
                                        rect.top=mTexCoords_v1*512;! l0 n0 D# Z1 I! P7 w5 J- `; g
' W* J0 e* g8 y/ b& B( H$ J7 ]# J* V
                                        rect.bottom=mTTFMsg->max.height;. J' t5 \& y) J* j! x1 H$ v

5 T  r' J  I  i& e                                        rect.right=mTTFMsg->max.width;
5 X. A% q  {* o9 G4 \: P, k; V) d4 G9 W
  7 `' q! T/ N- F# `3 p% @
( t: f: Z5 z& ]! s* E. O* N- \5 G
                                        ) u6 R# C3 f8 @  |1 c. C
6 Q7 a- j5 d, U& U8 m1 ^
                                        3 K) e' n+ Y$ @: A& U
/ K$ U8 \3 l5 w( t
                                
( ^4 J5 {1 T. K; h/ T& D0 m4 M0 m5 j! d4 b' X( a5 T
                                        //擦除(这段代码没有试验过,等做完输入的类在检查吧) + k. E: z& g" q  w% y) s
3 q+ P9 y  Y# ^8 s( N; z, f
                                        for( j = 0; j < mTTFMsg->max.height; j++ )
, \" h9 I, m- ^  Q  t. k/ e# K4 S7 Z4 R% g2 `9 {3 g* f+ x
                                        {
. F" M" U# S" B1 f! y, R+ M: ]: F" G  P# C5 \
                                                pDest=mTTFMsg->imgchunk.getPtr();1 G# j' d( @- z: f" D5 |
, p( p6 o. ?: B: c  Z
                                                pDest+=((j + rect.top)* (512*4)) + rect.left * 4;: Z" o6 I5 b. h, D" I
, T" [# W, m8 Q" c
                                                memset(pDest,0,mTTFMsg->max.width*4);
, y& E% D$ Q/ ]/ g% {) B8 N7 {+ v6 S
  F& D) s1 B; O+ W                                        }
. `0 \) O$ b4 }. ^# W: {# N, S( ?2 I
9 ]8 W5 W7 F! T$ z, e* Y                                        mTexCoords_u1=mTexCoords_v1=mTexCoords_u2=mTexCoords_v2=0;( R0 K5 g7 {% X# n4 f

* F6 B8 b# I; N5 [' q  P4 d$ j& _% ^  
" `$ @4 F: a9 R: M, v3 L2 u! D( W# z5 |- [
                                        break;
" ]$ J3 B& X  f6 t. {2 P
# Z. c' t) y% v3 u  S1 [$ p# B                                }
  V& X, A  z- w" p% ?
# R$ e" M. @0 }: ~                        }
% q: [* i* V6 M+ j; p+ r! x2 U& b& x( c0 H. r8 j* i7 R0 s
                        
9 n+ N1 D5 u$ R. p5 r9 I) x
' L2 I' t& d' ~3 p5 c+ |                        if(rect.top==-1)//啊啊啊啊啊啊啊啊啊,贴图竟然都用完了,没办法了,出错了 - ]2 \6 n0 w( c- o/ \5 L

) n7 p# l7 y+ N! Q. i* U                        {
5 G& U5 J: B, ?# \7 y; s/ d7 Y3 n& z5 f
                                LogManager::getSingleton().logMessage("你太贪婪了,用的汉字太多了,这是对你的惩罚."); , O: |9 a( R4 Z! s) ?* O/ M. F
8 D+ a$ K1 z4 ^
                                return false;
9 G) [  L* r# f% E
2 k7 R% @6 x0 U! d                        }
7 G0 _( j5 ?4 ~- ?/ V& o8 b  \
" {) w! w2 B  {6 t' p        
' U! \8 v3 d8 }* g6 C$ m5 W, v) h) {! \
                }- U' }$ W- W0 q9 o9 r. v; i2 J

3 K' M- [9 q; U                        7 y- ~. q( W9 u
6 ^6 v3 {- x. w: _
               
6 G! ~: m2 n& M) Y. B' B( r7 |. Y% c0 Z5 i
                  //以下画字的都是招葫芦画瓢的, - K( l) h0 O9 ~$ ~+ y1 v

& \- X. c! Z8 i$ Z$ x; W/ m0 ^; k                  FILE *fo_def = stdout;0 s$ ^( E. W. }7 u+ j6 Q
/ v# f% L, F8 \/ `3 R
                 FT_Error ftResult;
% n7 t( b4 o+ u3 N( c% B6 U
2 C) `8 N/ X6 t  
- v/ x  O% o  g- K
/ d$ Z5 e/ ?3 {; w2 W            // Load & render glyph
) V7 q6 [. w- Q& d2 r! {8 x$ H# ~# ^" {- `- ~! V3 w4 z0 ^
                  , O7 `6 s, n7 K( a' O
1 F  s$ h& ?, ?5 U) O  l
            ftResult = FT_Load_Char( mTTFMsg->face, unicodeMap[dwChar-161], FT_LOAD_RENDER );//读取字体 : Y4 t* y- |  f6 S- v
% E/ p* E0 \  ?
            if (ftResult)) y6 n* r( k5 V1 q0 M  A" V

# b9 B; v/ W7 C% t9 k% m            {
  A8 I- F2 ]( g) P# G5 s
  m# Z: y5 v* A7 E6 D" O, W                // problem loading this glyph, continue # _3 `; E, l% Z5 o

( Z8 W6 O1 n) q( Z: O' t. Z                LogManager::getSingleton().logMessage("Info: cannot load character " +1 G. Z# q5 ^2 v) J2 v4 }1 H0 R
+ v5 X# [9 N* |" ^8 R$ }
                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);
. C# H. ?. ~" ]. q' [/ _& @! O
: b! ?! o! f" R3 o' x                return false;//如果错误跳过 3 |9 ?- b  E" n& w, ]2 x& p  p

* z: F8 b1 f5 ], U1 D, i! b4 \            }+ H3 N8 j& @9 e$ P
/ ~6 M1 o# Z; X) z1 N
  
' I* m$ h, {- @. ?; }& j% P& o$ S/ A4 Z9 `
          unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;2 w. @" E8 A- S3 p* L4 `% h, g" g( b

& p# {) T% |: i" \7 x! Y5 v                  // 位图指针
( U# {9 b9 _% N6 N# v0 {0 u  ~, G  A9 f2 d5 g3 C6 N0 k( W# w
            if (!buffer)
4 J6 O# M, i6 ^
# i+ {2 f5 Y8 X' d- x: O0 h2 ]            {
7 J; h, S% W' E5 V: m9 L: K0 z: a9 v5 @& I6 ~
                // Yuck, FT didn't detect this but generated a null pointer! : X) x7 [9 U/ o9 E% O. P
% `# K- i( Y: h. ^" l) X, N6 D% R
                LogManager::getSingleton().logMessage("Info: 1111Freetype returned null for character " +
$ @7 j, w% R0 m
& T' d0 m% H) [1 E. P9 v6 P                    StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);" o* |3 n/ f1 o

1 {4 _4 M0 \8 ^                return false;//如果得不到跳过
% v& L6 {7 s' V
6 Z8 W" z, v2 L$ m            }
7 |, q- \0 X4 p# O/ l8 v! u
7 u  u2 E) @) ^0 y  
; w3 r: _! d8 _) ]* L2 L0 t3 ?2 f9 v& w( Q  C- j6 W' g, {/ b! |5 C* y
                         int y_bearnig = ( mTTFMsg->max.bear) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );
$ K7 k4 [3 E+ M1 |0 T$ |4 J/ {$ d* W3 }6 G7 A! H  V
       $ l) i: B* e! X
- n: x( L* s; I0 g+ h( v
                        - h; }: O1 E& O

* d! y  _9 y% P- w2 m. g            for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )7 E4 c4 e3 [- W+ V( N8 R
0 g4 I+ p& U9 _: _* O7 j
            {
2 T- o6 `! B) a+ T
- S; J2 S" I8 a7 K5 E7 [5 D$ v$ m                int row = j + rect.top+y_bearnig;$ [" H3 H# F. p4 ^) u4 O# |% l* V2 w
: i, T3 e6 N1 ~- o. T9 A: S
                int col = rect.left;//列 8 t( f/ C) Z% n; {. {$ L
! o- Q$ x. ^/ h' E! G* m; R( e
                                pDest=mTTFMsg->imgchunk.getPtr();
4 k7 @- |( t/ N) `0 b8 [1 X/ N. V  _
5 D. P. }! h$ s2 x  : p- h- A+ }2 V! f

* D' x) @' t& z/ Y                        
6 n# k( \3 M. ^' Z7 o/ w; w
0 W  d, \6 o- t- D' l; Y                                pDest+=(row * (512*4)) + col * 4;" m0 P% h! l+ q+ V, T$ @8 s& f

0 V" r, b; t$ j& Q, L* _2 r+ t/ w               for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//每行的点
. A; a9 ?$ F6 Y/ ~  F# X+ u) `
: `, j: c' K; C( k                {( y. b1 M; a; t
5 c: ]; R2 O, o6 V
                    if (mAntialiasColour)  t7 h% M+ e: ?% M, R" H5 o* X# f

1 a) Q+ h  `$ d) `                    {9 V1 l2 L# c/ ~; B
( k4 [% _. @7 L) i! w! h7 v3 I0 ?( l
                        // Use the same greyscale pixel for all components RGBA , ^, w5 I; p8 w* K, f3 o( P5 x- O

& d' E& g7 K8 E) n2 f8 {( [' D                                                        *pDest++= *buffer;1 p; Y8 v3 D. k% p4 a

7 W9 v" R7 F* i7 d1 M+ G                            *pDest++= *buffer;8 ?. p6 Z3 X7 k: i
" o4 V6 ~1 V4 b3 {
                            *pDest++= *buffer;
& P, _" i& U5 c# i
3 c( ]) p% C* O- N% h                    }
& t/ G7 Y8 F2 d0 ~
0 S  p0 ]' Z# Y* N5 j" m                    else " v- ^% ~* e6 B

2 A$ p- i( G0 Q2 m* }/ m1 @2 M8 L                    {& u9 p: f( N( ?9 X
8 P9 r6 G1 l0 V4 d
                        // Clamp colour to full white or off
% d9 H5 X$ C, m* ]0 q1 _1 S
$ S* F3 v4 ^( P% e7 c                        if (*buffer > 0)
* k$ Z5 E- C; G* f1 X
1 n( Z9 ]% s- ^3 y- M7 q                        {
& l1 m1 E7 r8 }" Q  w7 Q
, b5 L6 M, F% X( Z% u+ M                            *pDest++= 0xFF;
5 p: \6 @* U6 C$ M
4 C9 E& h) e) z8 g/ e; a. e                            *pDest++= 0xFF;
" Y1 j5 [0 F: J6 S' ^4 f
  [9 j+ h. ?9 m( I9 p                            *pDest++= 0xFF;
& [1 G0 H7 d# q5 n' \9 m1 I1 m9 _8 w; Q. P  ]' K2 P- k' o
                        }& B* ^; @3 n0 ?% K- c% h8 Z( l* ?

6 Q0 {4 a2 D/ z& z; B  W) \6 u                        else 8 E% V8 L: Z1 M6 A4 A

+ n% P4 U6 |  `% s9 M  t% o                        {
5 v0 S- _; y; ~0 u
3 d( M5 [7 `4 M' R                            *pDest++= 0;
9 @! L& F4 G" s7 F8 W. y$ v# @( K- w! S7 I% c; q, w
                            *pDest++= 0;
0 @$ R% Q/ Y  ?% c( s$ z: \" f
" G! z2 {9 J0 ^2 a) w  J                            *pDest++= 0;$ ^. ?. G2 a1 l! z2 Z# E. J

6 R, F- w" p1 Z& A6 o                        }% s" n* P7 V* J$ F  z* |: M; J- A
& b3 @$ j) v. M3 ~" ~1 C+ |
                    }& ^9 k4 X( R) x  D2 }- d

) f8 m! \; |2 H, w& }1 J+ m6 e                    // Always use the greyscale value for alpha 0 h0 f5 i: z( h

: f( |; e8 n( C6 x5 c4 {0 ]7 t  ^                                       
2 b6 P+ h. E; S" W9 Q. D
8 N& ^& ?& x" T3 s, ]                                //      LogManager::getSingleton().logMessage(StringConverter::toString(*buffer)+"is cool");
: v: O/ b& _+ j. ?$ E. F2 c! x! o3 ?  j' n, M& ~* N
                    *pDest++= *buffer++;" m( H) X# |' R# ]' B
$ ~% s: t- y1 t: g' p
                }) {  V- G- B6 S- i: o% Z

/ C6 Q& m1 R" Q( [6 [) O5 ?5 x                                
: d- ~: U7 t- ~8 Q, `
9 r& f# {: A' k: d, F- F                        }# J. S" o# W& a; N( Q+ ~  [
0 o/ O& Y% T5 i  J- k; M% H
                        // 设置位置
% c; u4 A, Z. o9 c: h0 P% Y: ?) H  d  J1 b9 y
                        this->setGlyphTexCoords( dwChar,
2 m2 @0 o8 D/ \4 O$ g; I* G; U+ q" y) A" D+ W
                                 (Real)rect.left / 512.0f,  // u1
& M7 Z+ e1 {! X% ]7 |, D) j% M1 x* O4 c8 Q4 X& e
                                (Real)rect.top / 512.0f,  // v11 b" Z  V& u7 m) {; U
' b5 E/ e% ?8 k3 u! U6 X& u: h
                                (Real)( rect.left + (mTTFMsg->face->glyph->advance.x >> 6) ) / 512.0f, // u2
6 R$ Z, O2 w# w3 m8 V. z& F! s
9 [% Y) p9 S2 F4 ?8 e                                (Real)( rect.top + rect.bottom ) / 512.0f // v2, Z3 A& s7 Z' N. H% s! Q

" f& e1 A8 V) h1 s( N/ r) `! w  ]                                        );
# W+ J1 m4 t  ~9 m4 X) ?" d/ e; q* y* k8 M9 `1 Y( E
                mTTFMsg->dirty=true;//贴图需要更新
& v' I" s! x$ a  I( Y, Y) K' I' l& `3 J. ^. I, M# c/ j8 @
                return true;
' _6 w  G7 w+ f+ W' b9 w$ X4 f( R. n% N# A' H3 n3 P
        }5 `8 T. \( o, y' }
6 ~9 t! C3 H+ ^7 i' |! A
  
" \4 G$ O7 A2 d. ]. T- I3 F' j" u
(4) 9 Y1 c+ |6 f+ L0 t

: |6 j6 L5 r! a& B1 f7 R3 [  R! y6 q        松口气吧,繁重的工作都做完了,就是更新贴图了。
# O! `4 Y# R) q# B7 v2 O, G4 [% H1 N) U7 z. e
        Font类中~' a0 k) y0 l, |; U+ j; g

. C+ F# V  x4 r/ C! z        inline void write()
, l! Z! ?- O0 U
) U1 _- W! n3 C, K# U                {
5 R" d" g- |. q; ~
- W2 q5 q' X7 \1 t7 w                        if(mTTFMsg->dirty)8 w) T+ y' S3 |( {

: e8 O' X6 A7 V  n( q                        {      
4 \# O! q0 y# H3 e
( Q' \7 y$ u5 v' g  O/ M- n6 m                                // 重新载入贴图,顺便说一句,类似功能的函数还有
. j( S5 N# E% `, ], m- i& s% {1 `5 b9 c, \0 o& j
                                //virtual void  blitToTexture (const Image &src, unsigned uStartX, unsigned uStartY)=0
8 J) [, G/ F5 }( }  \% Y, L9 J1 S6 B/ m
                                //和virtual void  blitImage (const Image &src, const Image::Rect imgRect, const Image::Rect texRect)
4 z  j) T$ _9 A* b  i/ L
1 [# s) k# y2 B/ h0 q  s4 d                                //不过blitToTexture()在ogre-win32-v0-14-0之前没有实现,没有尝试使用。 blitImage()就算到现在也没有实现。   m& H  q) F3 C5 t% A7 A: v' U

$ R' V, J. G0 A' G1 D9 d3 y' R  
: H! ?* T+ o9 B" S
2 L! O3 B+ Z: P' C                                TextureManager::getSingleton().unload ( mName + "Texture");6 L( d8 q& N0 d/ J# k& q/ z

9 ^) _( p  A% y) k# V                                TextureManager::getSingleton().loadRawData ( mName + "Texture" , mTTFMsg->imgchunk,512, 512,PF_A8R8G8B8, TEX_TYPE_2D, 0  );: b1 y& S# A4 u3 l2 L# [0 ]

( Q6 Z" `: _4 t' b2 V8 I                                mTTFMsg->dirty=false;
9 _* G+ u* t) D5 \) L+ M, e  F5 [6 W6 m0 I: v$ U4 }  U
                        }
2 _4 Z3 m9 ^. \7 o# U, G: X, o. Q# z7 Z2 o. q' [
                } ; U+ w9 q: T& s  t1 P
' l! {0 q* Y# M$ y% _
  
* [( Z. c9 K: b' u% {
% T2 \# U  ^4 t. Z0 C4 D. X  X         在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。 : \0 n# p+ f* a/ Y& U6 G

# N+ e2 K$ O7 V/ s+ X7 ~8 r8 O  ) ]2 @9 X6 \# q+ D! v
3 c# I3 a$ r+ G7 ~$ k& q8 B) w
  
% F0 Q. C. }9 u" u$ R2 F& a* w2 h) W0 ^0 {& d4 i% O
4.结果。 * a# X2 x, @$ @- o2 k& B
9 ~" b- ^* B/ k. c
        好长阿,写了好长。虽然多是代码,但写注释也很累啊。重温了这些天的工作结果。就像上一篇一样“在OpenGL和DX9.0中成功的支持了中文,但是DX7.0中竟然出现了运行错误,具体问题还不清楚,还望各位高手指教。”。不过本来OGRE就不怎么支持DX7的,不管了吧。OpenGL中渲染的比DX9.0清晰,是我的显卡的原因么?以上的winXp+vs2003.net+艾尔沙980se通过~。。
& U/ K6 _! K1 h" Q' G. E
3 i: k- E6 X( u7 W, {+ ?        顺便说两句,上次发表了拙作,没想到好多朋友和高人们找到了我。甚至联系到了一个南方的公司,说要做一个引擎支持中文的方面。但是卖完400多的火车票之后竟然因为住房问题作废了,5555,退票少了80元啊。还是自己差阿,如果再多学点可能就能要我了把~。努力吧,争取写《让OGRE支持中文》三部曲。
7 O& f; n; ?& i  E
7 l: ^2 h6 \2 L- \        下一篇应该是《可以输入中文了》。
2 _+ D# P$ O2 z/ B
7 i, m, a/ u" x& D$ J- @) s/ d# N# V        也可能写不出来的~~~~~~~~~~~~~~~~~~~~    " ]' T) s) O" I) d; e
" i7 m: i3 |  |' s
    相关文件
+ M0 F5 P8 n, v9 h6 f9 m+ m& C% r
* q! F+ h" i; Y; `' s+ w: X    chinese.fontdef//字体信息文件 放在资源文件加中 9 P9 J2 W2 C8 D  }4 w6 h) _* \

! ?8 F' a0 H/ t5 A$ q    font.png//字体图片 放在资源文件加中
8 ?. R. J9 A  R. X: b5 X2 D: U7 w) m* e* e: o4 {6 {9 I
  
% _8 u% N! P$ C5 i9 [
7 t- N9 c+ X* N2 H. z    OgreFont.cpp
2 S1 r0 R$ P! z) H. G' d4 j6 V+ h/ i! N% ~3 X! T
    OgreFont.h* J) S9 v) l" y2 N% c; ^" L
- `% t; u. k+ E$ p" F& @6 a
    OgreFontManager.cpp
5 L! S: w5 D2 y7 {& _- `* n  k3 B' O* k2 `
    OgreTextAreaGuiElement.cpp) l' f9 D& j, m2 n2 P
8 ]6 p7 L9 n2 Z8 U
    //上面文件覆盖同名文件 就可以 先备份 8 ~1 p# P" W# g( S/ a

4 o* @( A, I- _0 v   5 ?- j& c! y# g( E
, }; @! c( `: w' `1 T" s5 W2 Q
   solo5.ttf//这个是一个中文ttf 我直接替换了原来的ttf
! g1 ~. [  H. R/ }* ^+ P. L. @6 m
+ e. k. j+ Z, F% j   unicodemap.h//这个重要,是换算unicode码的数组(文中提到) 2 y9 ]) y9 O+ O" ?! a+ G/ f
6 @) B% s4 H( |. E9 {/ i
  
" f7 O9 [2 X4 `1 a& z0 _; a+ M( x! M0 K6 A' f$ s7 \: y6 }
这个是在ogre-win32-v0-14-0基础上改的(上次是ogre-win32-v0-13-1), & g6 `& s: v2 ^/ Q' z

- l0 P/ C  i# s3 Q) V7 K+ `请到http://sourceforge.net/projects/ogre/下载
! S4 e! ?3 e) ]
3 I5 G, h7 Q$ N9 R配套档案下载:http://www.gameres.com/Articles/ ... /ttf.files/file.rar 0 s9 w/ N: B' p7 T! p& i

& i: V9 ]1 Q2 Z: C 免费打工仔QQ:1850070; `+ u% I9 N9 R! S0 V/ p
& \$ m# {+ C# [
From: GameRes . f, \9 V$ J/ Y( V. ^* n
" }; N  y. o/ T
http://www.gameres.com
) m) |# R9 R* [% j( P& f0 p8 B) T+ G. Y+ P: J
上面图中“免费打工仔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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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