开源的图形渲染引擎OGRE(3) --让OGRE支持中文TTF字体! S! a# h, H8 |1 g% J' p/ Y
% Y0 M4 P: R6 F0.还是前言 / |4 W4 x Z" I" T/ V: N
; i2 `( X$ i' b* F0 \) O8 x9 R
如果你希望能看懂这篇文章,请先确定你已经看到了《让OGRE支持中文》(http://www.gameres.com/Articles/Program/Visual/3D/OgreSupChn.htm),因为本文是在上一篇文章的基础上写的,并且假设文件都已经按照上一篇文章进行了手术。但是如果你只想简单的使用TTF字体,只要下载本文附带的文件,重新编译就可以了。
9 o, r4 J4 P- u- O* B) L* I- }1 i' y( D0 B. s' \
1.检讨 5 {* L) v. U# ]- y" z# a' M/ [
; l6 o c! R1 W" U1 n 正如上回说的,我们已经实现了一个位图的字体。但是当冷静下来思考时,就能发现这种方法的诸多缺陷。读入一个2048*2048的位图,等于在显存中保存一个2048*2048的贴图,不说是否所有显卡都支持这么大的贴图,单是每个Font字体类吃显存的胃口,就足以令人心惊肉跳。如果定义足够多的字体类,我想你的游戏的配置要求,在某些方面足以超过《DOOM3》了。
/ Q' |* G# Y# `% f3 S
& E- z* S1 G% E1 S3 J& T. n5 N. H 而且这并不是唯一的缺陷,文字大小相对于位图大小比例相差太大,导致浮点数的文字位置误差很大,你可以在一个文字旁边看到其他文字的影子。(虽然可以通过增加文字间距来解决。)还有点阵字体本身的缺陷,就是字形单一,不适合放大缩小,一些文字边缘的马赛克,足以熄灭任何玩家的投入感。 ; H. M8 b0 T- }& z. C0 Y
, ]4 m) y" k) _% @5 {" ^# y
似乎TTF是唯一的解决之道。
* M* `" j- I9 {; w: E" K# e' V( `4 }: Q# \
2.基本知识
* {; ^ [* B! o | e4 n% c& ~: Y: [& p. l6 S
(1)TTF字体。
( ?2 r, }) f9 j) Z9 r* E9 [% M
. k7 [7 i, K1 M TTF是一种矢量字库。我们经常可以听到矢量这个词,像是FLASH中的矢量图形,在100*100分辨率下制作的flash,就算它放大为全屏,显示出的画面也不会出现马赛克。所谓矢量,其实说白了就是用点和线来描述图形,这样,在图形需要放大的时候,只要把所有这个图形的点和线放大相应的倍数就可以了。而且,在网站上有很多的TTF字库可以下载,或者你可以去买一些专门的字库光盘。然后在你发行你精心制作的游戏时,可以顺便捎上这些后缀为.ttf的文件就行了。包括Quake这样的惊世之作,也都是用的TTF字库。 - n- s: G' Y, _7 [1 h# j* l
( t1 h; P1 D7 ~; W(2)FreeType2库
1 w2 w1 w K# P
% M! {5 W: W4 M8 H. |" h 在http://www.freetype.org,有一个FreeType的免费库,而且是OpenSource的。它目前有2个版本:1.0和2.0。其区别在于,1.0只能读取TTF格式的,而2.0支持更多的文件格式,在使用它之前请详细阅读所要遵循的Licence,以下是摘自FreeType2.0对字库的支持列表:
4 \7 A: F3 v! P6 K$ j0 j$ ?2 Y, S2 e; \1 T h5 |
TrueType fonts (and collections) 1 U9 ]+ l! u5 V
; @7 |, o2 {( v" f! ]: T3 d0 Q
Type 1 fonts
9 K- z6 Y8 Q6 y# Z2 K$ L5 v9 M# }! a
CID-keyed Type 1 fonts
7 h4 b/ N6 a' J2 `9 ~1 X. m% @
3 | `; f# w/ D CFF fonts & Q3 F3 m" l( d
- O9 y: g/ v. u! O; s( [
OpenType fonts (both TrueType and CFF variants)
, [' m8 r' M! m, G" I0 {1 Q5 B8 X9 z7 \. q& |' H0 C
SFNT-based bitmap fonts
4 L: g! `! H4 e1 P1 `' Q2 X
+ g! V6 Z9 ^1 Z5 E% `8 | X11 PCF fonts 8 f5 A, Q' l6 N
3 n# U1 ^* \' C* Y; B Windows FNT fonts
5 X5 l! j3 y; P9 e2 d
1 f7 N& n: W$ h: C8 {8 z(3)“主体思想” , P$ L, c T; U7 h5 T
- O( O) v! a1 x8 l, {6 m 请参照炎龙工作室的《游戏中汉字显示的实现与技巧》这篇文章,可惜使用的是Windows API,作者千里马肝,上网上搜一下吧。
! E9 L$ o+ G! D4 M
4 \2 U& w3 w2 I+ X 附带说一句,上面两条都是直接从这文章中剪切下来的,>_< 不要骂我啊,不知道算不算侵权呢。 ( ]4 a" c: U9 [; Q2 X& j
! g; k }' k" N" ^
3.动手术---比你想象的要麻烦 0 ]0 j- B# r: r% i$ q
(1)
* y" `* I; V2 d 首先要告诉字体类,我们下一次渲染需要哪些字。以便字体类可以在需要的时候释放不使用的字体。
f8 N! H9 h4 U8 H9 D$ i2 |
5 H# l1 n- F: e; u) l# J 在Font类中~
' W, B4 P1 k; U/ a A l' T1 C0 ?- _" r( |
a.增加数据 bool mUsing[OGRE_NUM_GLYPHS]; 用来标记文字是否使用。
( E; {& v9 r& X2 M# Q( c% O, l: s# \5 d' s i7 b- O8 F) j
b.增加函数 ; K6 T$ j, w0 j
% c5 q, w/ A* G9 t inline void setUsing(std::vector<unsigned long>& caption)- B3 y9 ^5 ^& s( g5 G) C
" Z1 x- ]7 V6 u, i) \- _
{
, `+ W) o" V+ ^
! f4 i1 `# B6 l& i0 e memset(this->mUsing,0,sizeof(this->mUsing));
8 f( p' U5 n$ F. ?' ?* h- Q4 ^5 |( [4 A T, |* k3 z& A
std::vector<unsigned long>::iterator it;7 I2 ?. J# V, ~ s* n( n4 m
( t" u& o0 A" ^! n) K4 Z) Q! {3 [
for(it=caption.begin();it!=caption.end();++it)4 I' F+ {5 {7 i1 F& R
8 `# p6 S, Q( e {5 ?; d/ {8 g/ p5 f+ A' u) n; ]
7 f" P& o+ _; t$ ]( W, }- b if(OGRE_GLYPH_INDEX(*it)<OGRE_NUM_GLYPHS)# U) h1 _% q( y5 I- O
, _( @# r* k. D" [ k1 m7 t this->mUsing[OGRE_GLYPH_INDEX(*it)]=1;//标记文字为使用
( l, p' U' t! D, X& i; v/ u+ \7 U. h& D) {; @, ~8 k9 X- y a
}
6 Y o( X, M# L! r9 u' s8 H. a- c/ F! B! m7 }& n
}. w6 I1 N; a4 D
. i& ^5 }' A# }3 v, o$ l$ l
并在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。
' v# s" X# M% ?2 j, C(2) 8 s3 d- Y8 X2 I2 \2 R( Z
, g( w; ~7 D' k% ^6 E
然后是修改void Font::createTextureFromFont(void);
6 |) Y( ~( g& T" I3 q I
0 d% P8 l4 u. S, H: k' E Font类是通过void Font::createTextureFromFont(void)来把通过FreeType2分析好的英文字画在一个2^n*2^n的贴图上,然后再保存英文字的位置。 5 D3 _$ \+ N: U$ S* @( s
@4 j" p- q. M 我们需要修改的是:
6 ]" }- e! X" w9 `* A$ n! `+ u7 i- H
a.从函数中分离并保存画字的FreeType2和辅助变量。我们通过一个类来保存和处理这些变量。 9 m6 o* y; l4 k+ }
- ], t: H5 Z+ S. k& @* P% ] class TTFMsg. s' }4 w0 [; F! r6 W+ W
8 w: D) N4 T; E& `! w0 g
{( j/ n9 ]" N1 T
1 u# D: \( l: E
class Max//类中类,用来保存几个"最大",
/ q8 D9 r. q) M
$ x7 E- x) J+ |: T {
! R1 H6 C; C+ l' c) F0 c" ^8 Y0 u/ W1 i9 k0 k' K+ F% k P
int nothing;//这个是用来占位的,没意义,反正没他就运行出错,可能和数据对齐有关吧。 ; Z/ t- D8 z# p+ r6 m% Q! _- v1 l% j D
! @6 N2 |1 W% \( B% } public:
: `* B0 q/ j v5 `5 n* P int height;//文字最大高度 % N( D) ]% m1 x7 l! P2 v
int width;//最大宽度
4 j8 |" v8 Y; c# ?" Z int bear;//最大空隙?
" m2 Z( c. ?8 f4 w, d };' P0 e+ t' d3 W# O8 a1 G
public:
; }! h% j' S) o7 \ FT_Library ftLibrary;//FreeType2用 5 R( w/ | n! U2 j& _# v# W! _
FT_Face face;//FreeType2接口? $ x- W- \, P L8 M. a
uint char_spacer;//文字空隙 . J& X: X0 F" a, \" e6 K4 R
SDDataChunk ttfchunk;//数据块,用来保存ttf信息 5 z4 o% P. V3 q
FT_F26Dot6 ftSize;//FreeType2字体大小
% s; ? _ o% V6 }4 Y std::pair<uint,uint> point;//在位图上画字的点
* o! ^$ z& p- G' f3 S+ w2 @" { SDDataChunk imgchunk;//数据块,用来保存位图信息 9 @4 m/ M9 |6 h9 I
bool dirty;//标记,看是否需要更新贴图
/ X3 {* L" ?( w Max max;//几个最大
7 c% l8 K/ j5 t% x6 Z2 X3 }
5 U7 c7 `! _& |) h# x2 i inline bool init(Font* font) //这个是初始化函数在void Font::createTextureFromFont(void);中调用.
* X1 y. U9 C% @7 g
/ I& [9 o V1 i0 E2 w$ O { % v; M. d( w7 u
4 s, c/ k! l0 @( V" C @% I9 W
//以下都是初始化,大部分都是从void Font::createTextureFromFont(void);移植过来的
1 S9 ?6 x/ t$ |6 a7 S3 j3 ?, U3 u
+ W9 F% [# p# U4 o) w- f1 w dirty=false;0 I$ q- O, f' E& Z
/ U: h4 Z& Q0 p; v* @ if( FT_Init_FreeType( &ftLibrary ) )
; h. Z/ J0 {1 J( w( _8 t/ i
# T8 C) ^4 y S Except( Exception::ERR_INTERNAL_ERROR, "Could not init FreeType library!",
9 G' Y$ B; H1 Q5 E1 m$ L
- m& R! Z7 E$ O1 ~* X' ^( O "Font::Font");3 F7 v/ s" w9 X2 I% U
. ~! {/ B6 b/ J* r3 O% t4 ?
2 A# w; h8 [% b6 j0 H' ~8 ?/ W6 V$ L! L/ U
char_spacer= 5;* C& h5 ]1 H* v, A1 u
2 _! i3 f4 v7 | FontManager::getSingleton()._findResourceData(font->mSource,ttfchunk);
- ~. t9 i* {4 F7 y m4 ~' F0 Y
! E! a) G# }/ M! b if( FT_New_Memory_Face( ftLibrary, ttfchunk.getPtr(), (FT_Long)ttfchunk.getSize() , 0, &face ) )
' J) E+ J( e) g$ e. D9 H
5 Z |$ r, {2 G0 [) E; l& R0 i% @7 D Except( Exception::ERR_INTERNAL_ERROR, 1 z3 Y- E- R, J5 Y. E
$ A2 [) }( `9 L, b5 M
"Could not open font face!", "Font::createTextureFromFont" );
+ r4 K+ w( ?+ I1 r3 G
0 x I. V/ X8 e& J6 ?5 B ftSize = (FT_F26Dot6)(font->mTtfSize * (1 << 6));
3 S7 \/ {, x4 {# n. M8 z$ ^+ d, |( n6 f# a0 S% E, ? J$ ?
if( FT_Set_Char_Size( face, ftSize, 0, font->mTtfResolution, 0 ) )
* ~( l1 w1 j% A3 |5 A: y8 F
/ D" W ^6 e0 d' P Except( Exception::ERR_INTERNAL_ERROR, 4 w( S; N- Y9 `
+ j h e+ w6 q p9 j: |0 x "Could not set char size!", "Font::createTextureFromFont" );
$ U* _. {/ f4 Q5 J. [( X
' p% r9 X. g$ o! \( K 5 A! K& V! V7 b0 ]( V" B
4 b( E' e" `& N% b2 Z2 X4 w, p
return true;& g U: O1 g" i5 j c2 ^/ V
- x. ]& C: d3 L, h1 h# S
}- z1 p; A3 Z3 b2 O4 \3 g
7 C8 s, f3 y" N/ L' C3 ]3 x7 n
inline bool done()
. {# u# U; z: ]- z5 F; [' P5 X5 J! U, @4 d/ g# z' I9 E% {
{0 |+ ]9 _/ k9 a4 L6 u1 F
: P1 y0 D' w9 ]) w% A //在Font的解构函数中调用的,本来应该调用下面两个函数,但是不知道为什么一调用就出错,不用倒没事。
5 _" a: N3 N, m m) P) N) F( m/ U6 r4 M
//FT_Done_Face(face);
2 ]6 b7 v) h' S5 S$ G% S7 S4 r5 K; O T$ J5 \, l9 @
//FT_Done_FreeType(ftLibrary);: d, [6 A1 C4 j: ?
$ {" D" P& d. R' V' J* m return true;: C0 ^( F5 Q9 H0 R
7 s% Q# f' V/ {" o7 I2 j( V3 t
}
- ~8 h7 s3 ~, ^1 i4 \3 a
, Z. z; r5 W1 H4 n# Q( N inline bool getRect(Image::Rect & rect)//这个函数以后用的,是用来找到可以画字的贴图的空的位置 - @, W$ E- |. R# O. W( i
: ]! l) ^2 A' I; u6 M
{
. X$ t( E4 _2 U, L# e6 H+ N3 t* p- B: [/ F( L! g! Y1 m
if(511<point.second+max.height+char_spacer)
. Y# ~, l6 K' e0 i1 d: N- i7 L( F H) R$ r! A+ j! B
{
& x1 R# b$ c! b* [& L0 N* O4 }$ h: u9 @* g
rect.right=rect.top=rect.left=rect.bottom=-1;% g# \1 L* o+ b0 d9 e u
9 W+ J; w& u( e" O( S* `1 \ return false;# d! ?' Y* N+ m B7 K' Z. L) N
5 O, c6 f7 Q, |/ p9 r
}
3 [% E p- H! u0 p& ~- N# J$ `3 s, G: b8 Z/ z4 Q+ X! @( _
if(511<point.first+max.width+char_spacer)) ]. S- f6 Y7 M
}( Q; \; P. r2 U6 j' \. F% E
{6 r9 f* z( P: P8 v8 ]
0 r( z2 Z5 H; Y) b) n. Q
6 Y2 V ]( q5 h
+ c* F4 y! s' [. a# ^! n
point.second+=max.width+char_spacer;1 c3 S6 s/ w9 }. |: I, j. ]( B
' J& d0 ?; a/ v5 L' i) r point.first=0;
3 P1 ~6 W% [, _6 X
! C! V/ ~% p1 l- F6 l w) D( h if(511<point.second+max.height+char_spacer); O, N) c2 N; X
% ]: G2 l* f% @) O {0 n& `' R+ O- V" D+ u% f
y0 V+ H8 `( |
4 L" e9 P9 P. W' s( a' s T0 R: ?( i! n/ [ ]$ [2 }
rect.right=rect.top=rect.left=rect.bottom=-1;, k: G! F) x; P& ?) \6 w: ^
& s! |' s; m, L) b3 A& r1 O6 Z1 B
return false;$ H/ O( S6 g( y* v
0 P, p- e; ~& E1 ]- G/ j2 g1 ~ }
: g' k7 w( P" V1 o. y! ` M# Q( V& m0 E, q3 |
}7 p+ O8 P' S8 i x0 V6 ^
5 a$ h# }: ?% H+ g# @2 Q
rect.left=point.first;
4 l6 M" q' t6 s( e( Q. W( _% B& e" p3 f$ i9 `
rect.top=point.second;6 i% q) M( ?3 x# S$ @' G5 d
5 a1 f5 g! Q6 L) W rect.bottom=max.height;+ J2 k6 }$ ?' b! z! o1 I
6 o) l0 c m. r/ G7 c, H rect.right=max.width;( n5 \) [1 X4 F. g. Y( `; W3 m8 @' e
. ?, y% t; g; l, J
point.first+=max.width+char_spacer;1 O7 c; H: j x) n' b I4 u
0 H2 r, D! e5 B' t9 u/ i
return true; u+ T1 ^2 d, o+ \
( K7 r( L/ ]9 k1 v( j
}+ C9 V" z. Q2 ~) A/ U" S3 b
' a( F5 _4 e& T; S- F" H, {& b };
3 ?& j( w; ?9 j/ F% j- F! o6 g3 v9 n- T& [# T
上面的类定义在Font类中,在Font中增加 TTFMsg * mTTFMsg 数据,并在构造函数中 mTTFMsg=new TTFMsg;
0 `% o0 u" m2 Y" i1 Z% R1 g1 v+ {5 \
, V) ` ~8 O5 z! @0 Y4 v" `/ C' d' T- ^
9 G5 e% B9 i7 |7 c
2 a7 f' B2 F6 O5 V: n! A2 P% d 正是修改void Font::createTextureFromFont(void);函数,主要几点,首先是分离出很多变量和构造到TTFMsg类中了,然后是贴图从2^n*2^n变成固定的512*512,为什么要这个数字呢,因为256太小(废话了)。能保证512*512大小的文本区不会出现不够画字的情况(所有英文+符号+没有重复的汉字),这个安全区域基本上是够用的。(什么,你要画满屏幕的汉字?哪你自己看着改吧。)还有一个重要功能是,要找100个汉字,找出最高和最宽和最大空隙作参考。修改完成这个样子了~) `; w! X7 e1 c) o8 F
D- p9 U/ c4 k8 l5 k3 E void Font::createTextureFromFont(void) T+ c7 l( d% R3 G2 Z
8 Y# q+ U" M' e0 e+ x, X$ E/ s {( g* [/ q& @4 x$ y+ T# q5 r, u
4 k6 V. m! Z5 {) w& w$ A. D mTTFMsg->init(this);//初始化FreeType2. J' W% Z) e& C1 |( P; |6 M5 Y
9 _% T) e2 `4 G! V& U0 F
uint i, l, m, n;
3 Y0 {$ ], z6 q0 ]
$ B* g' r8 w& r; n int j, k;: Y p: n6 b k) p8 o
0 E7 d( X* X' ~0 |1 W$ F2 s3 @9 V
; h( F$ l0 `( A3 X& h9 U: ]" a$ `% P+ f# h+ b- \
/ R" L) l* K5 \
O7 \! C& y) a8 |$ [: {; d$ F FILE *fo_def = stdout;//啥意思?我看不明白 7 f& m7 g' C/ L7 h
" l) ^( R* x5 ^3 P# U' e
' N# U W. U% a
' b0 J- G! r: A6 Y4 ~$ `5 Y int max_height = 0, max_width = 0, max_bear = 0;
% P" a3 q. h3 r, c& ~4 D$ a9 |3 Y6 {1 o+ i7 _
3 f- x3 H2 {8 O0 P8 H# z
! a( \: v" d- { V6 g+ m0 f uint startGlyph = 33;
4 ` r1 F+ Z( I* O- w" s2 r) j7 l
uint endGlyph = 167;
+ Z# d w- y' I& e& s, d& }) q" G1 c4 n& J4 u1 O: f
5 a' F t" e; d( Y5 ]- u1 w% C1 U. a7 z4 i/ ?8 {: X. n) C
// 找英文的找出最高和最宽和最大空隙 1 r+ A% L! q2 d. a+ I/ }0 V+ e
' h, n. @) X6 ?6 Q; O4 S9 X2 @ | // Calculate maximum width, height and bearing
1 J' B2 H: n. H* e# W
2 A, s4 n T# e, w( G for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )
6 c0 m) |9 c# E( a, y& L
+ m. H! \" p1 X$ \ {8 c0 u$ s9 W! ]! Z' [2 \) M) h
/ b4 T6 S/ Y: _8 {2 P. h: V: b FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );4 o/ d9 ], z- S. f9 k8 R
$ C% `! k* p8 d8 e
//以后的 <<6和>>6都是FreeType2中的数据和我们使用的数据的转换 8 }, K' x# m3 O w$ Z$ r7 y1 S
7 M( @# I3 Y) [2 c
if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )$ G# H- h, f1 d; @2 c7 m
3 X! K! G9 z% x- o) U* I
max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );6 \/ ^- N: j( H# K7 I
# v7 J- f7 V; R/ d6 n if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )% l2 c0 g, f* u
8 i! ]9 l5 }! k& Y3 ? max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;
' D$ t D8 D9 G* e9 b
9 v2 R+ {, _1 ~7 ]7 I 4 _. S7 W/ k( F8 r& x
; G/ C/ o; i; W) ]
if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)
' T: }9 a- b. ~* l: F) {7 i1 L% Q H4 Q" w) x( D: T
max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );
5 A6 ]- t4 g! r$ V6 Z) l9 |; H
5 c% d; z5 B* n! O7 ] }
* s! u5 A: p0 E/ U5 G) t, D" M: f2 X& |# }! J
" g8 g6 _- n# u# c) Q2 w
) c7 [: C" ~ D4 I
# N+ g2 f3 d, w1 Z! G# Q" ?
3 b2 }7 [- @/ v) f. s( F, K //下面的for是找100个汉字,找出最高和最宽和最大空隙作参考。姑且认为最的汉字就在这一百个里了。 ( D* \0 l' y& |* H+ p
, g8 x2 y7 s M. c for( i = 20643, l = 0, m = 0, n = 0; i < 20743; i++ )
8 X" R( a" u+ }' b! t. l% l
7 T& R: W% t; `" Z P) b4 | {3 S! Z0 [( O2 o
) x4 w0 c& D$ N
FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );
- L' X! [) G# h O1 @ E& g, a/ o5 b. |8 [$ e7 Z
( n- b' U. ^' K+ C, i8 f8 q+ g
3 R! J8 B' A o" |. j+ {; c if( ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY ) > max_height )
8 q; C: B4 Y5 D4 v# c1 D3 Y7 ^4 B% A* B* O) R% |
max_height = ( 2 * ( mTTFMsg->face->glyph->bitmap.rows << 6 ) - mTTFMsg->face->glyph->metrics.horiBearingY );
: l6 ?( o" a2 g; ~1 n c
# Q/ m( `1 M( m; V9 O if( mTTFMsg->face->glyph->metrics.horiBearingY > max_bear )
8 T9 O3 w+ a3 {8 X* y7 x
$ r; N9 [% U: h6 P- J max_bear = mTTFMsg->face->glyph->metrics.horiBearingY;% r9 V! L8 I( T- s3 u% Z
y% H! X. e6 @9 K# M) v0 A& d - x/ p& Q% V& f0 T+ R7 {, J8 D
. ]1 `9 u2 m* G; P
if( (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 ) > max_width)
2 T+ B+ B1 r' P
9 ~' w8 m& ^: A/ u; Q" H# p" O max_width = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );) ]1 S0 I8 b1 B; T6 _. g B" `
' O0 `$ Z; a! M9 V
) v* X* ~1 _/ L
4 h7 B* U7 M( {& V5 x/ i
8 p R7 u5 I; G" ?. ]9 q6 i% T9 j) K9 a3 D: m
if( (mTTFMsg->face->glyph->advance.x ) + ( mTTFMsg->face->glyph->metrics.horiBearingX ) > mTTFMsg->max.width)
: w! K' B2 j1 ~* P1 O# [# w3 R2 o
' G0 F/ W( s) n) C mTTFMsg->max.width = (mTTFMsg->face->glyph->advance.x ) + ( mTTFMsg->face->glyph->metrics.horiBearingX );) y+ \0 p& X9 o/ v6 N) G7 C {
3 s" X$ \8 w4 U0 P2 J }
) T4 }, q" q+ v; l
8 K3 x% d6 U ]
& ] ]0 T2 m7 ]4 \8 k) z. ~4 e8 ]: D# e! F8 j
//下面几行行不需要了 我们要512*512' v4 A! j% t n' z$ ?' U$ Q$ W' p+ d1 x+ Q
" R6 j3 m( d! X1 Q) @0 l; _
size_t tex_side=512;//就是这个了 512: C, x# ]+ I2 ]# q, {2 R! q
3 C' b: M5 B0 N0 @9 ~# g //定义数据宽度 因为是32位的位图 四个char为一个像素,为什么要位这么大呢,难道不能用8位的么,我尝试着改来着,不过改了之后就不透明了。望高手看看能不能改。 6 i3 G' O% a5 s. z3 A/ f8 Z, i
; T: H Z4 g- m i& H/ {# S
size_t data_width = tex_side * 4;
" D* u6 @8 Y" C1 H
- ~! }' P# h9 D5 C* u
( Z& W7 l/ O* w2 w, R* [ ~$ ]( N- L3 W
LogManager::getSingleton().logMessage("Font " + mName + "using texture size " +
/ g9 ]1 B' G- Q( g8 L7 W/ C: d: T b! m& N" p
StringConverter::toString(tex_side) + "x" + StringConverter::toString(tex_side)); s. [/ G8 o2 f& ~! b) b
\3 k$ E3 R$ V% h3 L
0 _# P+ ~$ }* |# [7 U) |7 N' S' M. J8 y m; |4 V! N9 W! R8 L
uchar* imageData = new uchar[tex_side * tex_side * 4];//设置一个空间用来保存位图 + h# A5 U; T, a: J
0 V% G/ a, b. ?( `+ V // Reset content: m2 p" r0 u. i9 B* y# M. U
9 |( e$ q+ i8 J memset(imageData, 0, tex_side * tex_side * 4);//清零 1 C( `2 f/ l) w% K+ k7 @( c
# z5 L% ]7 O: d. v
5 r2 y+ [7 ?& X5 P
$ w( c5 t3 z5 r for( i = startGlyph, l = 0, m = 0, n = 0; i < endGlyph; i++ )//遍历每个字, - S1 I0 H; b: C b: i% c
! y$ [2 G0 v: {3 L. O/ [
{/ Y, f7 j( }! E- f+ _
8 T t: d G) |/ ] 4 \3 s+ V: L3 w5 I: h$ B
/ Y3 u8 z9 r' M
FT_Error ftResult;
9 l' Y+ `0 j ~3 e0 J. I
- P4 y" k0 t! _6 |
2 \! Z2 k" D4 [4 j. l" ]$ t) j5 {9 C: N6 r9 ^. [1 p
// Load & render glyph
$ r9 A$ v6 L- J2 `( Z/ s) k* [, d3 T Q e" o. D# ~
ftResult = FT_Load_Char( mTTFMsg->face, i, FT_LOAD_RENDER );//读取字体 2 o: E- z6 ?+ A2 m, i2 ?& o% A
& c3 ~% J) T6 c2 [" ^
if (ftResult)+ H) Q4 M1 u8 h+ @1 S, g# D, P
- U; C: z- N+ h1 F( T9 X
{
- \+ N3 A |+ C; X z: q- ~# F6 K+ d9 V1 K7 T# s$ A
// problem loading this glyph, continue " F! z+ M# f5 O8 k
8 Q/ H M# y, m e& N- ?5 _& b
LogManager::getSingleton().logMessage("Info: cannot load character " +8 ~* ?, r2 t- Z) q; q2 }$ j
) r6 h# B- o& d" l" S6 a) p$ V7 [
StringConverter::toString(i) + " in font " + mName);
" S2 r5 d- l* d6 B& a0 C( O% i9 J; f ^
continue;//如果错误跳过
9 L3 D, K( U6 O% x: C3 d6 y. q1 f6 |# S) b
}8 A! ~9 t! ^2 |: @ w
* ?* L1 C6 ]8 }5 { 7 T E8 P( V0 Z% h
: |" n( d" }9 E8 V; u0 i' o: v
// 应该是字宽
E8 Q. H9 p9 \% R
( J/ U" h9 ~2 U- d x! m! H FT_Int advance = (mTTFMsg->face->glyph->advance.x >> 6 ) + ( mTTFMsg->face->glyph->metrics.horiBearingX >> 6 );' t E: @0 W& L5 T
$ e# d) G; j: H6 Y0 w
2 E* u; B/ P/ o! @- E% Z/ Y+ w7 ?1 t x
' @& S7 Y: C5 B% V8 J9 g4 D8 H // 得到FreeType2的位图
3 @8 ~ r6 d- s1 F- B- K+ M" Q9 N7 F2 p' L" x* X- p
unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;. z, n$ d5 J9 U$ v, i
3 \( u. }( C [+ [8 r" J
% J& x" E3 M- B
% q0 m4 W9 G" Q+ J: @ if (!buffer)
. _' z0 r3 x* J/ ]+ K9 E
9 b C3 C9 _; ] {4 F( `+ K. S' q, d8 t" E# y
: ?! m, G5 s7 D5 P) c
// Yuck, FT didn't detect this but generated a null pointer!
' {0 x7 w) y7 g, B
2 U2 @$ h2 S. ~# T LogManager::getSingleton().logMessage("Info: Freetype returned null for character " + T8 Q* W5 K& O" `0 b1 d* C, F
+ r; s- p7 Z% t9 L
StringConverter::toString(i) + " in font " + mName);# d/ t$ J5 ^- J
' y, D( |! A) f2 a( C g6 a; @
continue;//如果得不到跳过
/ }" Y; {5 ~8 t% R0 @% e
2 f; ]& n* u$ G& q v" c }' x: g& Y# F) Q3 b+ N7 |/ e+ M) S
9 r* a4 J% P# E, I4 ` i. R# ?2 B
A) o# g/ \9 u9 S# d5 C% H- I" h3 o- B/ o! l9 x+ D9 _& Q* o
// 得到y的空隙 (最大空-空-本字空)就是说空出这些字底部就平了 $ Z2 P% ^0 G9 z) o; s, D% L
! z, w. p1 l) y int y_bearnig = ( max_bear >> 6 ) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );
+ w- u2 w. S" O, L% p$ G: G% p# p. \) N; [3 E0 L! z# j3 b, p9 P1 c: w' p A
! c9 H5 a3 C, {( P. m
$ Q2 [# h g. G9 _+ c+ p( o for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )
6 d* U+ s5 x' ^" A8 M0 _, `/ Z4 ~- e) J
{
! P. m" o& q( b9 r0 `8 |$ }4 r: i2 |9 v2 g4 Q
int row = j + m + y_bearnig;//相对行+本字在位图的总行+空隙
0 t) h% Z2 e$ [/ Q0 c1 D" U' s( c* F& M3 \
int col = l;//列
5 Y# K, a: R: h# P, ]# ]! U3 d# Q1 o" x; k/ C9 V8 i
uchar* pDest = &imageData[(row * data_width) + l * 4];//找起点 ' w8 S* J8 n1 @2 G
3 ^# r" A9 I+ f8 |7 x4 K, ~ for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//画图
. ~( T! g0 s& T# A6 ?- b. q1 W* ^
{0 c5 K3 ~$ h7 L* Z( \- w
\5 b, v- d( y7 X2 U! | if (mAntialiasColour)//看不大懂,难道是灰色字体? 1 Z8 \8 v7 L8 H0 m
5 R; p. F& V2 H& M
{
$ U4 R) |3 u+ {) W3 P5 J! ?1 o- T( w7 \, Q
// Use the same greyscale pixel for all components RGBA
; x+ f, p) |2 b k5 U( B8 d! N1 a- ~; ]" L# i& z9 ~
*pDest++= *buffer;' n$ F& j1 v5 C4 v
Q8 y& B8 {. j# j* n *pDest++= *buffer;
o5 K- s% S9 n, i# O. o8 h
0 \0 r q" h4 O; m0 y *pDest++= *buffer;
8 ^' z" h6 `# D. q' x
+ ~. ]% s- j( f: _9 p& L/ U) ^/ W }
4 v! n2 D8 r/ Z9 e8 R p) L# ~* O6 T( \1 ]) i. r$ J3 G! n
else
* R) |9 w# E! Z( ~% m+ ?, o6 j
4 y& v/ G+ J& m" j5 A/ {- t) ^ {
5 g% L1 c* Y! I, J4 S* u4 @# @7 n
/ _9 q% J4 k. D6 M // Clamp colour to full white or off & ?( g/ [5 v/ Z$ E
7 _0 ^ o V# K1 L. a# p if (*buffer > 0)+ I i* i4 c. T5 `6 s' R& @9 g
0 a- {# g& Y. N& W0 ]) {5 X2 A {
: I9 S) g4 Z3 L' s
6 Y0 L+ D5 I4 r# l O! } *pDest++= 0xFF;, w3 ]7 w! ~( |7 L5 l# t3 L2 ~4 a
S: d' l" b- y& k/ s6 I1 b
*pDest++= 0xFF;1 @7 u; t$ {5 t+ Z( a
0 _8 W4 j# t \/ w5 _
*pDest++= 0xFF;2 ]- u" Z! K: j1 x2 O0 a, m
% O5 d2 j5 S6 H$ ]/ \9 t1 f
}
* }- u! q, g( a4 B2 A8 I
7 G2 d5 {) h4 i else + o7 Y4 q) _& T# `
# x4 J- d3 u* s: N {
3 o2 R- f1 ]/ c" |. w7 `1 {
3 c9 X Q$ G- c0 d/ @ *pDest++= 0;
c8 M* G4 n6 y! e! D. O% P* {% ~" n. r# q
*pDest++= 0; i4 L5 l3 K/ d# C: ~" W
* a; \2 q7 m: z1 e
*pDest++= 0;6 m' f+ b7 E% {; x+ d/ J% N% l
1 K* A3 L% P* d8 I8 x
}$ _! U" k3 X! w5 j
' U' J& \2 E* o- H/ Y, ?4 r
}
+ J) T) z$ L5 ?, x: x' `! \2 h
0 k1 V2 Q1 ~% r. J1 T // Always use the greyscale value for alpha , z9 N" |- S2 Q* X3 j
% x1 K1 T& r2 `; k( z; a
6 n0 _' {3 u: X' |9 U1 p
' f& p" z! x# d% c M *pDest++= *buffer++;//alpha! 我是一点不了解了为什么是这个?
' m4 p/ k# G. V' M9 y% ?$ `! [5 } C- {
! J4 m; Z g) L }
/ }* B# K3 ?# R# q' a- W
! c3 \8 u i; V }) }; v2 f. [ E. t% h
$ w2 j9 J. ?, v3 Y
? A6 U/ d. H( Z) }& r! d
! U( q. a# d1 {& D this->setGlyphTexCoords( i, ) m. V+ G$ W' D3 m$ @
/ q9 e; G2 ^! s( R8 G- u/ E (Real)l / (Real)tex_side, // u1
& s4 N, ?% K7 N# A0 [
. j% v( n. u, Y, [' P (Real)m / (Real)tex_side, // v1
! j$ D* [6 Y) m# l) L. c; B0 n' m2 G9 |
(Real)( l + ( mTTFMsg->face->glyph->advance.x >> 6 ) ) / (Real)tex_side, // u2
& `! A4 x, [2 ?. }% }# Z2 y& `( t" G2 ~1 |
(Real)( m + ( max_height >> 6 ) ) / (Real)tex_side // v27 o4 R( [ L( k+ X& l! g
, f" e6 Z$ ]) M! C1 ~ );//设置坐标 % I; r, _4 y4 ?6 u7 [% f8 [& t( W9 {9 N
' k1 Q6 { C$ `6 I8 i! X4 }: ~
' { e, b+ S: m+ s; }: Z6 U" K/ Z5 h5 x1 ^0 i- r
// Advance a column
0 `: ?1 Y4 j; {6 V! h1 d+ M3 `7 v2 E
0 A" f( |; @: W4 h6 k% j* i) H l += (advance + mTTFMsg->char_spacer);3 R; {2 i" R; V2 N; U
1 r0 s1 A$ w6 i# w. ]- l
//l+= 本字宽+字空
$ f8 |6 P7 Y8 P. L
: U9 [3 H& @# j* k2 s; | / U5 D2 d) b9 Q) r7 R
" s, ~- D2 h# F5 |% \$ F$ ^ // If at end of row ; O) Z" }* s2 }+ H% t
) S7 m! C H: Z; T) { //如果到头容不下一个字 4 T* K% T, [/ c, K4 I
- K! o$ U: |9 w" n2 b; E: ]3 z
if( tex_side - 1 < l + ( advance ) )+ ~; [* ^4 t- k! }2 X, O
' M$ k! W6 }4 L' }" J M {
t7 s* \$ w- Y# u7 |, @% e
2 Y: l# ^. |4 n3 [5 h! V/ p; R m += ( max_height >> 6 ) + mTTFMsg->char_spacer;
L0 n) B+ O0 T( ]: W5 X8 A* o( r4 s9 }0 M; ^6 m
l = n = 0;
, S- L5 T6 p* d1 I8 P, m8 p. X2 C6 E% S
}
; R' W) U% p" s0 F/ M3 W# _ X5 x$ _8 K1 L+ D
7 L! ]% X/ f2 H3 m7 k% i+ V- ]) d" h! s
}
6 b1 [. b" L% h
5 w* }/ T# u$ `) d* X // 把信息存到我们的mTTFMsg中 >_<
* N! w$ b# K: s; }; P3 W& i# v. Q% A1 ]2 y1 | e
if(l)
5 z$ S) }0 D$ g! N# W2 G% d
/ s, q$ a. ]5 x2 a& `8 f/ T, B0 r1 B1 v- [ mTTFMsg->point.second = m + ( max_height >> 6 ) + mTTFMsg->char_spacer;0 p) N5 K% \3 E) l- b% v0 z
" q& F# P7 P8 P! r' R4 n
else
. Y& M/ s; x& t2 Q
0 Y4 M4 x# A0 }+ N/ s( z6 j6 M2 F mTTFMsg->point.second = m;
- Y) A8 u8 [$ Z0 Q" ^; O
6 ~$ F* \, g6 {) ?, ?# x+ D$ D }* x8 N - p9 F* p W3 `4 j2 t
" y1 ]2 M5 A5 y j. y) g/ D mTTFMsg->point.first = 0;//另起一行
) o2 b. m% X: W0 a1 @
2 ^( L; i; C! n7 o( _0 h3 m2 V. R* ~
$ Q$ {- L8 N: x7 c
( G6 Y0 Z6 r1 {* g% R //下面是保存几个最大。 + {1 O' T5 D3 P3 Q+ s1 H
3 ^4 o, D. z: j( i4 X+ n mTTFMsg->max.height = max_height >> 6;
/ f. c& e! h7 ~# g) i
, o4 ^9 K5 y, [) N- h4 { mTTFMsg->max.bear=max_bear >> 6;
* b, D' n' `. T! ~, a8 f1 m& d) g, U9 z9 o7 N7 _: e" K
mTTFMsg->max.width=max_width;9 s2 n9 y: _- J9 S
) T/ e& _2 u3 v' Z # D& E+ q& D" s4 V
& A2 D" l3 h5 h. [
mTTFMsg->imgchunk.allocate( tex_side * tex_side * 4,imageData);4 H* A' X o+ A7 z5 g4 Z
9 J1 ^7 b, u7 v N8 S . B/ F5 c: C+ d$ N! z: \1 N7 A7 k
/ a. C6 l/ P p
//不知道为什么要设置img这个中间变量,似乎可以直接从chunk创建贴图 8 N# _( K2 z% H7 y1 p, x
- Q9 P- e/ j# { //--Image img;
; D3 P2 F& _ ?/ E; o4 ^& K$ u9 K# e% m, R
//img.loadRawData( imgchunk, tex_side, tex_side, PF_A8R8G8B8 );
* j9 e$ U) P3 v; a" l
+ F. t6 c& x* ` }) Z+ {! m/ l& W + b7 {2 E- n6 z* b4 F0 n( B5 J
7 a/ w9 y; M- X- d- x5 V u+ d
//贴图名
1 s6 F& \# G W6 ~. g4 }+ t9 i1 l- T1 o `8 S; f' e/ \
String texName = mName + "Texture";
% V( m- y5 s; h4 V
7 X5 B, t( S+ f // Load texture with no mipmaps 0 \* w2 z \7 M
% G4 }3 j' Q7 n+ L G$ _. o* ? // 把从img创建位图改成直接从chunk创建贴图 # q G. U/ Y1 I$ I9 |/ ~% F) n! O
: y# I% H& b% p# L5 g
//TextureManager::getSingleton().loadImage( texName , img, TEX_TYPE_2D, 0 );
$ F7 {! ]( l; M# g, z* E9 x7 J
4 @4 M4 @% p5 q/ i/ u TextureManager::getSingleton().loadRawData ( texName , mTTFMsg->imgchunk,tex_side, tex_side,PF_A8R8G8B8, TEX_TYPE_2D, 0 );( N* i9 f+ e8 c) V7 a
! ^6 W3 ^* m8 h( m7 W* P) H! i" p. }) C TextureUnitState* t = mpMaterial->getTechnique(0)->getPass(0)->createTextureUnitState( texName );0 L( r' a; C6 {* |
( D/ g P. L4 @9 Q // Allow min/mag filter, but no mip
* j: {. i" O# w. J+ J( a& ~6 p' e. x0 K7 Q! W
t->setTextureFiltering(FO_LINEAR, FO_LINEAR, FO_NONE);! _! |& T! L/ @* f/ f% i
+ `4 P7 k- E/ O2 O) f4 ~( s // SDDatachunk will delete imageData
7 B0 o! U8 b+ B }: @% Z+ }3 {9 n- a, s F$ R2 F
~& J6 f4 }$ }! X5 G
" o% y) u" H5 i, Q, W! j( A3 b }
! W$ z$ `: S1 U- d6 N( Y7 C7 [
" u# o: J. z7 E: M1 X 你应该对照一下以前的函数,改了很多的。
1 Z: w8 e* W" M
9 e1 K; M( T; b5 {, @5 c : d! V, m0 G( z9 Q% q/ }
9 g' }3 @2 \5 n6 b1 ~, G
" ]4 `1 t- M' | y |& L
1 M) G0 O/ w* d
(3)
" u* g+ |4 y- T% f& H' f" Z4 D3 }1 X) S9 M
然后最重要的是动态的申请和画字。
2 A, K2 r+ ]% ]% ^/ Y9 ^. [5 C- P% U
首先最重要的是我们要一个方法得到汉字的unicode码,我们用到了unicodeMap数组,提供了区位码到unicode码的转换工作,等一下提供这个表给你,好不容易从网上找到的阿,可惜这个表没有中文标点的对应,如果希望支持中文标点,就要努力找到unicode码并加进这个表了。这个表是这样的 char c[3]="邸";unicodeMap[94*(c[0]-0xa0-1)+c[1]-0xa0-1];就得到邸的unicode码,不知道为什么没有5165~5169的unicode码,是轮空么?
: d. T* b) _" z. m, E- R" h* |( S% ]/ ]7 I5 ]( Y
7 P" J/ |$ p) D% C0 M3 m
) W+ c+ c1 I7 c7 V) y. \* F8 Q 申请渲染(字)
5 D- s. P# E: z/ q4 P8 \$ d* V& [" t9 K
{$ M$ x, T' w; k+ o2 t1 h
' N. S/ T$ T% H: T8 u @$ a, @5 i if(有这个字). J# K/ x. Q. p$ D7 P$ u8 s
1 W$ m* e, w3 ?/ r2 o5 X
返回位置 |$ z5 q/ @/ q
. ^/ G! w3 H5 S( W8 Y; h# l5 E else' m: f1 v4 C: m5 X/ r( U
( r, [" K; C' R( ?6 X! Q" g
{# |) Z9 `. G9 \1 H) E! ]0 x
- w4 @ g7 N) K0 u3 d% E
if(有空间)
0 Y5 ~3 e- h# H+ M' B o) d. @, X: w% S/ h, p
画字
; Q" q+ t% n+ W0 \" P2 s% x6 x. J8 @0 }9 S4 K8 I8 x; S0 o/ o& j9 X
else
. [ d$ j4 f/ I$ h8 y) E$ j6 K/ H
找不用的字//找不到就出错,没地方画了 % Q [/ M1 B; f+ K0 ?
6 F- Q3 V. |/ O; |9 {* i1 M
删除 在这个位置上画字 + e* |! K' |) S+ W
; v0 ~3 }8 c6 L) }2 ?3 _4 |, v
返回位置
8 |# B1 q) Z: u
; b4 F( [) K( @- A9 W }
/ B4 d. ^6 d) i% U2 }) p1 P! f4 \- d: b1 v, { d+ \
}
6 n# [* S/ v. p# ~- e1 _. o+ @8 q" m! ]( u0 k/ z
上面很直观把,大体就这个意思了,申请渲染的函数是inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 ) const。去掉const改一改。得到
* R8 H# }7 Q, o0 N0 _- E/ J. I6 }* G0 e6 [9 |! `- X+ n( D& m* H8 @
a.申请渲染 . ~$ H3 }1 r K3 m
@0 O' H7 G! t h4 }0 h3 l. m% ]4 l inline void getGlyphTexCoords(unsigned long id, Real& u1, Real& v1, Real& u2, Real& v2 ) 8 v* a6 q! e+ |( |# P; N7 |
- _0 x- R& M( D: j
{9 H# k2 d# n# C/ {5 R9 _5 e
* u: f# @9 |7 _- n0 { unsigned long idx = OGRE_GLYPH_INDEX(id);
% J5 G4 H1 g" X* V) F# a7 S* F
. L0 z* }6 {" _8 b" ^' Q: v8 s& z if(this->mType==FT_TRUETYPE)//ttf? _* L% N$ `1 c2 a
" U% {/ x4 \; d6 h
if(id>=161&&idx<OGRE_NUM_GLYPHS)//汉字?
6 `1 c- Y' \( b. V! s5 g+ l; @8 c/ @* k; k3 b
if(!mTexCoords_v2[ idx ])//没有?/ F) |8 U4 s% |% S8 {4 N4 `/ L
, Z: p- y _' J. V' c$ Z setChar(id);//画字去 & I5 j+ C+ q5 b+ }( Q
/ G* Z n5 O! g9 {" v , p/ V) l$ k0 j5 b7 _! E1 u7 T
1 H, ]4 H3 f; ~$ X' t3 Q
u1 = mTexCoords_u1[ idx ];5 g5 N; J$ W: |4 H1 x6 h! O
# n V9 L2 w& K1 I; x6 l7 a
v1 = mTexCoords_v1[ idx ];
! ^. k/ _- N( P# T" L# l# l! b1 K4 ~! s3 U
u2 = mTexCoords_u2[ idx ];. C# P9 {- I5 G4 f; v `
9 F0 Y) N6 F" A4 Y" J
v2 = mTexCoords_v2[ idx ];3 F$ C& B% L- b' F# D1 m+ ?9 T) I
; e/ J0 j. |) O6 k7 h
}
& e+ P6 c- b0 S: }! \6 I8 ]
# X. u& n: L8 }( T6 f& g b.画字等
1 T) H. P+ E# X! @7 _3 {
5 B# ]" L6 g6 y( u5 g) @ bool Font::setChar(unsigned long dwChar)
( u- q, r0 L6 k- j: p+ D6 e: J
{
/ ^1 ?7 f1 W5 N3 A9 @" C
Z' U! L, K% W4 d; { int j,k;
/ I T1 P% O- Z% h8 r
9 W. a0 D. b# k uchar* pDest;//操作数据的指针
- F% y' O1 m( B8 ]5 Y0 l k3 [$ @" U, A# _& o" V) `" F
mProportion=0.8;//不知为什么,总觉得中文都太扁平了,所以设置这个参数,在《让OGRE支持中文》中创造的参数
6 L9 u& [1 `7 b; c, a( i
6 e# l; k' X% f. p/ @# s Image::Rect rect;//画字的位置 2 b& ?) ?4 @0 [
. r& @0 W9 j& m* B+ f3 c
if(!mTTFMsg->getRect(rect)/*回头看看这个函数吧*/)//如果得不到空位置 8 z( B) x2 @( j% K& e- i; z
I& Y' T1 c h+ d4 w0 f V {% L9 q. h" X9 A8 M# Q! ~, G q
' d' M2 ]8 y) P4 E$ |! S5 Y for(int i=161;i<OGRE_NUM_GLYPHS;++i)//寻找不用的字 # F# n. `, j. V; @$ K
" y0 A& Y" d6 G
{& a- e" s! g9 b
; Y! D% A0 J1 t. z if(!mUsing&&mTexCoords_v2)
- _! C5 d, u* N3 N( l
2 ]( s* M' S; a0 _0 x5 T {
0 s& m' P' Z, Q$ w9 R+ x1 X
# _1 k$ O8 P$ }4 x! Z, { // 得到坐标
6 z7 Q* S# e0 d
. x5 ^& F0 i9 Z5 d7 a! e3 { rect.left=mTexCoords_u1*512;( w. |/ P: r: T& ]; Z
- n; V8 [, L+ ?: E
rect.top=mTexCoords_v1*512;
& Q$ n/ _9 |9 T+ c1 {) G
* T4 T8 V9 g6 c/ Y" u+ ~/ F& d* S2 ~, a rect.bottom=mTTFMsg->max.height;3 `, e; Z$ L) w
( r2 C3 A9 f# x f% B. y, Q
rect.right=mTTFMsg->max.width;
& @$ @& E2 L2 [
! g3 P: N4 y; |; X! {- @ 1 r8 D$ x* g* ]) [
1 K/ ~9 Y1 ~! F$ N. ~) ~' W - R5 @# @5 n) }" ?
) l3 r( A" B' q5 E
" d# @. p) z2 b
# }( M: Y; K8 { 0 {0 E3 M" G9 o1 r
' v( F5 N/ C3 b6 g* W //擦除(这段代码没有试验过,等做完输入的类在检查吧)
5 z9 K6 w; A( a; j. k+ A, i$ Z& e% i$ I. U1 f' ]7 G# e% t" V
for( j = 0; j < mTTFMsg->max.height; j++ )" ~, Z% t: T# k9 b% F. L5 L
7 H: {$ l$ p+ f* |% H# l8 T
{
- U# b- s, ~' j r* Q5 V; m5 e
8 J% x/ \% C1 }3 Q) H5 w pDest=mTTFMsg->imgchunk.getPtr();
: [4 M( C6 n5 i6 i9 w: j' Y1 u8 g' F; v" D) o
pDest+=((j + rect.top)* (512*4)) + rect.left * 4;
6 o8 l; @3 T' p7 \4 K6 m; |- W! ~4 ]$ G" x1 q8 ~( `
memset(pDest,0,mTTFMsg->max.width*4);
& s R1 s& G P2 n3 l( b- v8 S; @/ L+ C. i* k8 h8 k
}* ]5 S3 U' Z( E# T9 ^
. m3 O9 n( l/ @( `
mTexCoords_u1=mTexCoords_v1=mTexCoords_u2=mTexCoords_v2=0;
# B# }8 D) T% e+ ^
0 O* i8 N$ u9 o, T6 D
$ ?' U9 Y' y2 z3 r/ l% B: g. c* S% H9 t' [& [. P$ k
break;
% `- F. ]: S" ?7 ~% F5 O) n
4 q. e0 e' _0 f5 b4 |0 j }
5 t" [% J' s# X# g2 {
1 {1 v; L1 f, O9 I; V }
/ J. W% f& r* E5 x3 v* Q5 Y( ~3 v+ L) }; Y
' {5 R' a2 q4 ]( k2 Z% P! v
+ Z! t# l2 ]( s- d1 T2 R if(rect.top==-1)//啊啊啊啊啊啊啊啊啊,贴图竟然都用完了,没办法了,出错了
0 j$ G# g) ], \& R3 _2 x; F8 W! m# E! @ F
{/ A$ }& _% I q4 B3 @4 H7 O
9 b4 J+ |7 b' U, H$ ?& m2 \, d+ A7 x LogManager::getSingleton().logMessage("你太贪婪了,用的汉字太多了,这是对你的惩罚."); ' |; L: M3 V+ l: |2 A
c/ `! _7 J0 C0 o" G return false;
0 w9 l# C9 `! [' P3 S" F5 q" q$ J( `: r; Q! N1 i
}
' s5 J, E) m; I
: ^' u3 M0 H% N' u3 Y& }
! q& u5 a, Q$ r
" r2 l$ H6 n" u9 J: C* k9 C3 G& g }9 V. b( R- H' D
3 _0 ?' }0 a% C, N1 a7 a7 J6 M7 h
9 j& P8 o2 }! ]; `1 R& z1 ]7 h* B9 g, Z4 h; H7 u1 P0 ?
& o2 N- A* C: s0 f$ ~2 j* T9 o4 ^
8 \ s9 `5 l# ^; h8 r //以下画字的都是招葫芦画瓢的, # Z- U# C7 Q. S6 [& b+ x: @- w
+ W. z9 u. Z% R/ {" j8 } FILE *fo_def = stdout;
6 X0 f q, i7 [8 Z' `" @/ W6 m& H) ?0 }( F& t0 O Y
FT_Error ftResult;* g2 S7 A) d6 P$ w6 J! X8 j9 _
1 u9 U2 U! a/ m+ v$ Q ( v/ i$ f- U: K& A( U
# l% x% j1 U5 v4 F" z% @( t6 U6 |5 \ // Load & render glyph
W( L6 e9 s+ ^4 D% C7 M/ ]
* |) z3 y" B3 X. | Q& V $ u# A: L& m' l$ l3 h. d! U/ H
8 ]) |3 j# w0 \2 J" n7 ?+ q1 s5 n
ftResult = FT_Load_Char( mTTFMsg->face, unicodeMap[dwChar-161], FT_LOAD_RENDER );//读取字体 5 U( t1 r3 g* J; O! D
. _3 D1 ^8 ~ G# N/ i
if (ftResult)
6 ] G" Y# n: y X# I
. u+ n1 m/ ~4 c {
; \ f- K% O. ?! c5 M' F$ B9 ]9 f! v' V1 @! G. B! W! B; ]/ n4 L
// problem loading this glyph, continue
9 @& M1 q" g5 X/ ~/ Y9 _. M& O; P; }7 e" S+ O( ]; `/ A
LogManager::getSingleton().logMessage("Info: cannot load character " +0 j" Z2 q9 u5 f, V g& V
- x' l! V5 v# |( | StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);- R6 t# n Z2 U; f9 Q* m
+ x3 }5 T: a2 S$ F return false;//如果错误跳过 ; ?* T" d5 I7 m4 S
' G% d: ^# G1 g' Q" T9 f' \; u }
! V5 m3 Y M, Y5 h: Z, f( @- ~6 l* W/ u
, I) t* s) C5 a1 X+ ` F
/ M1 y+ z7 e$ [9 N7 y
$ i+ O" F7 L* f( C% `6 v& j unsigned char* buffer = mTTFMsg->face->glyph->bitmap.buffer;% ^- _ K8 z" v6 P) J0 Q8 P
, ?# b; `- Y, z2 R2 Z4 f4 \3 W1 f. @
// 位图指针 / q( k' Q% n+ q1 s
$ `' N' K1 N7 g$ [8 ~ if (!buffer)
3 t- w5 R; e8 b" \# @ B" u7 k% k/ U8 j5 [4 W
{
4 L1 d* s! ^$ v& L6 Y
; b$ G. _8 p7 d4 ? // Yuck, FT didn't detect this but generated a null pointer!
% _4 q8 ^( ]# @+ n8 a2 r/ x6 h2 ]6 \& a8 c
LogManager::getSingleton().logMessage("Info: 1111Freetype returned null for character " +1 v0 T* P' ^1 J# U m
$ g3 @ q( g8 o3 N* |3 B StringConverter::toString(unicodeMap[dwChar-161]) + " in font " + mName);
- l! ~- N& Z' m3 L' m9 h. X6 E3 {! C6 E4 |; Z
return false;//如果得不到跳过
. Z6 C* R; D: P: z9 x0 \8 y: o$ `7 v \# }6 T' o
}
: R4 u/ r5 o$ |; B1 E
$ X `( w3 L4 X7 O2 v) C% V 1 G2 A. R# P5 p
* C$ ?7 U9 M. I$ m/ f4 Y int y_bearnig = ( mTTFMsg->max.bear) - ( mTTFMsg->face->glyph->metrics.horiBearingY >> 6 );' S. t) S, Y( `
9 i5 i5 A4 L5 l- y1 @
8 C2 l7 h O8 {9 r
6 r1 z+ |7 E4 g* h0 ?1 K. O
' ^3 F7 O7 `) Q d8 @: \
+ N `+ j8 q# Q: @4 V& Q for( j = 0; j < mTTFMsg->face->glyph->bitmap.rows; j++ )
' v! p. z1 |1 z5 p, P5 W# |. I1 X4 Y1 n9 Y) N! c
{" J3 I5 E0 s& D' [( E5 ^% `( J
" z `5 \, b/ Y
int row = j + rect.top+y_bearnig;
% n+ H6 S# r, O2 o. R- j" k
5 f+ N9 I, ^4 J% M7 C int col = rect.left;//列
- B: e* o# x# q0 X4 x7 v" E [) V; c( Z$ @
pDest=mTTFMsg->imgchunk.getPtr();8 V: `) y% a5 D! Z) G. e; n7 {5 A
n2 c- W' W- [8 ]
6 P5 ]) u: B9 i( k, c) J
; K0 ]0 a$ Y& d* K @6 _) p
- t# p4 ]% D* A7 q* z, D4 V) b" J5 u( }# W$ {. x
pDest+=(row * (512*4)) + col * 4;
( H' Q& M& Y7 u Q
. M, l" d2 S) k& E" ~ for( k = 0; k < mTTFMsg->face->glyph->bitmap.width; k++ )//每行的点
5 ^8 _9 [( T3 V, ~5 H, y! Y8 U f4 @; ^5 x
{
+ X( o! x" \1 ?. A7 {6 y; Y! A6 I( e) o
if (mAntialiasColour)" u, s, q- J9 c! R
9 q9 T; ~% Z3 B/ f. d {4 @( U3 U0 d4 F+ a6 \
4 T. n1 u( p4 {) T5 b
// Use the same greyscale pixel for all components RGBA
3 I3 l% Y; r) R% I
( Q* c8 {2 `0 V0 l; k4 S4 f *pDest++= *buffer;
/ n9 [( \" Q+ n3 A- Y: i- Y8 [: R* J+ i8 f) b
*pDest++= *buffer;
) _. X W. G; n# ^" {8 a, z7 U4 b( W; J* [
*pDest++= *buffer;
. w6 x% ]1 K- K: o, u+ S0 A6 d! k* \1 i. k+ `& P G+ D' T7 g: k3 t* e
}' L3 x5 L! o& m& N& p. Y
; Q: h9 {9 C; y* }% ] else
% o+ B" r, a4 k" v( Z9 n" Z& N6 {2 {3 D' n8 U- X+ \. B+ x, ^2 D. o
{6 h1 n1 L, t- I7 t8 _
' A% |: H! M! O- T) ]8 f) g( H
// Clamp colour to full white or off
! Y# q5 s: X- E1 Y
& m6 d- B' j6 ~: N" ]4 Z if (*buffer > 0); n5 }, g [2 W% G0 l- m* G% _+ Z
& W9 M6 {2 S. F {4 \# V0 \! m; e1 R3 ~( W8 w) G+ w$ n
/ O9 E' y$ {" F1 u% j: |
*pDest++= 0xFF;
( |" r8 C: g3 u" b# h/ h- \: g% [0 N m
*pDest++= 0xFF;
8 |4 a- k1 W o6 h8 g& H, ]
6 x1 |9 i$ n/ Z5 s *pDest++= 0xFF;
: a: F6 o0 m0 P# f% z
" O1 f5 Q" k0 j W }& R0 W7 [! `3 H' ]! b
9 h* k. c9 ~, ~5 F else
+ e. U* }5 B8 W6 L9 B, T- \2 o% q5 ^+ f0 U
{
+ f9 _- I0 j3 v$ n% o
! n- c1 o& M, H% c/ Z+ ^ *pDest++= 0;9 T9 G4 n: n/ u$ Z7 F
- V/ K- U8 b& M, [7 |8 A$ l+ N! j( I *pDest++= 0;
9 ~! s) o2 V% l! s: U: x, `6 }; N9 ~5 {5 h
*pDest++= 0;8 M% m) r/ x6 K6 A8 \: ~0 L7 y# U
( U1 Q* X# J8 ~! Q
}
0 A- p+ @! t. s, Y d8 `) B. w3 A- a% n! y F3 ~
}
% s7 i6 X8 [" ]* L* A. M
! a2 I: ^! w. _) p+ S$ |: s // Always use the greyscale value for alpha 6 K7 u) v5 C. \* ?: T+ f
" Q( g+ W( i- E9 v, U
1 ]# E4 a) p' k$ B. g5 o Q5 Z' U5 N* I. ]2 j4 A& J1 X. [
// LogManager::getSingleton().logMessage(StringConverter::toString(*buffer)+"is cool");- x3 ~8 T0 \9 p$ k7 @
) V4 r$ z- H6 h5 x5 x/ ^; t9 _+ x2 w2 V+ \ *pDest++= *buffer++;
6 W- X' M( D/ s* F) L# p0 G' S6 Q$ k7 f& I/ H0 x% Z
}$ M6 F. ~7 x& A j( [* z
# n& |, @2 r/ C2 c
" U* A3 I/ G6 {7 A+ v. i- q. I
$ F8 i" q1 W- B" a( b- i9 V( V
}
$ m0 L: g u, C6 z. {, W/ ?( |6 o, w. _6 F4 M; R
// 设置位置 l9 I, v! ^& s: S
8 ~. K0 E' K# q \1 k5 g; d
this->setGlyphTexCoords( dwChar, , _9 o A6 T9 Q" o- l' ?. w
" g" k; n2 q* x. ` (Real)rect.left / 512.0f, // u1
' }% T+ l, t$ E9 k- E8 G/ I! ^; |" b* M1 z5 P$ a
(Real)rect.top / 512.0f, // v1
( K- X9 k* |$ z8 ^+ n# n- l A" L: T. w$ `) j
(Real)( rect.left + (mTTFMsg->face->glyph->advance.x >> 6) ) / 512.0f, // u2
& g" @* F X( a+ m2 C! q
! a# N F( l" \& x+ F (Real)( rect.top + rect.bottom ) / 512.0f // v2
5 ^' P) p, _% D; K1 T
) \3 a: M% g# v; r( T- d, e$ k );
. q# P3 e$ m2 l* {/ J+ n% R3 ]9 @* e9 d, A0 U
mTTFMsg->dirty=true;//贴图需要更新 / T7 j f* @& J4 ^+ W. }- h3 M
* |- t) t6 }6 Y" ?: Q3 D return true;
0 N: _% V7 p. O1 g0 l. t5 K# V# a$ F) T8 {$ K, z% G3 _, E
} O" p+ D$ Y8 V1 d+ B1 z, [) A
7 V/ L5 d8 ]0 d: F5 ]: v
& P, u1 P6 j" K8 o) Z0 B
( \/ p1 R+ f( `4 b8 p7 g# G(4) " U$ z& V. |7 O% w" b4 v3 o. A
7 i" ]: U4 @; f
松口气吧,繁重的工作都做完了,就是更新贴图了。
; ?: @. V4 H# W% [9 E& s7 ~; g5 x, E
Font类中~
* h4 \3 U- {$ s! e
" L% y1 G: S3 B2 H inline void write()# \/ x5 @3 o: E% H
% I: o/ S# n# t4 c* {( `
{5 V; Y2 f% H, c1 J2 `6 z d6 Z
9 p- Q5 |; ~! }9 t4 ^' N1 Q
if(mTTFMsg->dirty)8 d7 t, y/ P* X
4 E( k. y( H6 C0 g
{
- _! k' k2 P% ~' \. G8 k% m7 t4 j% u; m7 z7 d9 X
// 重新载入贴图,顺便说一句,类似功能的函数还有
0 _5 B' @& Y0 Z; g3 u
9 l# n a8 l/ E //virtual void blitToTexture (const Image &src, unsigned uStartX, unsigned uStartY)=0
: m( S& s: r) L) L; \
8 L; M$ ~2 H; y O5 W //和virtual void blitImage (const Image &src, const Image::Rect imgRect, const Image::Rect texRect)( e7 X4 J2 p2 v) O' ~( }
4 F/ L C# T, R6 Q. l
//不过blitToTexture()在ogre-win32-v0-14-0之前没有实现,没有尝试使用。 blitImage()就算到现在也没有实现。 5 T" C+ H' ^! {) a+ U& \) J
$ v1 U" Q! o! l3 h b, d6 v! y. n9 X6 f; [4 G/ q
8 P* ?- r0 O5 U% `2 A/ k TextureManager::getSingleton().unload ( mName + "Texture");0 x1 V( d+ o& v/ W. c: P% j
* N- f2 m {1 ~6 b# p5 N TextureManager::getSingleton().loadRawData ( mName + "Texture" , mTTFMsg->imgchunk,512, 512,PF_A8R8G8B8, TEX_TYPE_2D, 0 );& h) [3 y* R4 p3 [3 M" h% j6 ]
$ _( o) Y' V3 }5 V
mTTFMsg->dirty=false;- d3 J2 O) K- x1 B8 Q" w! O
% j7 }& g/ L. y+ N& [ }
7 L' h2 N; I" i- Y8 Q2 Q- Y5 g1 k- K
}
+ [( K+ ?! g" D) }2 V
7 K- x s6 Q! B0 M1 Y) f + c7 _( z. V* \. w
/ o6 L- K2 z {# x4 ]$ {0 G9 b4 y$ `4 x 在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。 p+ ~& Y$ ?0 e% A3 q
' x% X+ M" v0 X. S, U ' c& N2 T4 b- R! r
! w4 Z1 U% H+ h, X
" H2 p5 y% J8 ?1 {9 l3 l* [ H* k
; `1 p ^! R: B4 o" n" v1 `
4.结果。
: m6 h* d5 e, ~0 _ c. M" T l& W& u: h! U3 M
好长阿,写了好长。虽然多是代码,但写注释也很累啊。重温了这些天的工作结果。就像上一篇一样“在OpenGL和DX9.0中成功的支持了中文,但是DX7.0中竟然出现了运行错误,具体问题还不清楚,还望各位高手指教。”。不过本来OGRE就不怎么支持DX7的,不管了吧。OpenGL中渲染的比DX9.0清晰,是我的显卡的原因么?以上的winXp+vs2003.net+艾尔沙980se通过~。。 % ~. l; q9 K& d8 d3 @. D
" ?6 D4 G" Z0 a8 X% _ 顺便说两句,上次发表了拙作,没想到好多朋友和高人们找到了我。甚至联系到了一个南方的公司,说要做一个引擎支持中文的方面。但是卖完400多的火车票之后竟然因为住房问题作废了,5555,退票少了80元啊。还是自己差阿,如果再多学点可能就能要我了把~。努力吧,争取写《让OGRE支持中文》三部曲。
( x: ?, q6 [ Q' U. }! U3 @6 [% D \5 G: k! |4 E5 R
下一篇应该是《可以输入中文了》。
: i" f4 }; V! H0 d
. i$ i4 P0 k1 B 也可能写不出来的~~~~~~~~~~~~~~~~~~~~ ; D. C1 ~! p0 _9 `* x2 p
; z8 {% y9 V- d8 l1 g3 M* z
相关文件
' z9 Z/ R9 n8 R4 M* m5 O) J8 T G1 h4 d q$ F' F
chinese.fontdef//字体信息文件 放在资源文件加中 $ n, Z# u/ p/ M+ w5 O o3 p! N
3 |1 D$ T5 M, {: C( _7 G6 ?+ R W font.png//字体图片 放在资源文件加中
, I3 J. x$ A8 F$ ] q/ A% B# \* o. l. `1 V; H( I. K
9 G9 B& W i% J @: c4 W
. Z; F% X/ z r5 O* Y. `9 u$ Q OgreFont.cpp$ I. J9 d# W! _* N8 A8 m& \
0 U# b" i1 _5 J, ^) u OgreFont.h
/ `* q+ g. B) _+ h# x# I
6 E5 t, Z; S9 D OgreFontManager.cpp
6 K9 _3 W8 U( j1 b( Y) n9 L/ y1 H
OgreTextAreaGuiElement.cpp8 G: Z8 \% l" u& ?$ v; V2 p
2 E. a% Q. ]( w4 {+ U: L. k9 q
//上面文件覆盖同名文件 就可以 先备份 & x$ ]9 {3 r) m5 f( F
1 y) z: d4 c N
7 y: t" i1 i" A: l% w7 N
3 A- ^0 @/ U4 T$ ^. p0 k! } solo5.ttf//这个是一个中文ttf 我直接替换了原来的ttf3 R& K" S, [& W. U* a
9 ?* d1 W' z( v& D# ?1 `. W7 Y unicodemap.h//这个重要,是换算unicode码的数组(文中提到) / A1 h \0 d; b, Y4 P& x( j2 K
0 M6 Q- M+ x) ]) L$ G & e8 H4 H3 U& d
; s4 v" `, n+ V, A# B这个是在ogre-win32-v0-14-0基础上改的(上次是ogre-win32-v0-13-1),
# {( k% l6 h7 J" n- g6 M* v) D: {. H: v8 e- a" ~* ^
请到http://sourceforge.net/projects/ogre/下载
1 j( X& }1 V: R) f4 K, H8 W9 X3 g! E. D. {4 h8 X! Z
配套档案下载:http://www.gameres.com/Articles/ ... /ttf.files/file.rar
, q: K2 T# f" l) O& q. U' P3 {5 e8 e. M/ N( ]8 c
免费打工仔QQ:1850070
9 b2 ~$ ?0 y8 [. |; k5 C+ v1 _
( h" c% @; P9 M0 uFrom: GameRes
, `2 s4 @2 X0 _, X$ p& u/ Z9 `4 ?. {# e
http://www.gameres.com
6 L* _5 n' n/ d. q$ N
" x) ]% Z' M1 N. W上面图中“免费打工仔TTF:213.786”是TTF 其他是位图的,中文的位图字体也小修改了一下,支持半角字体了~ |