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