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