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