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