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