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