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