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