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