原文) l& B) `/ K8 A) k' d/ C
http://tsuui.is-programmer.com/a ... st-under-win32.html% e6 d, k5 k4 Q" O
9 o! S& H; h( t* }+ L l/ w$ Z% Y+ q有了FreeType2,这些东西都是历史了....这文还是留着吧, 以后参考5 F J* C, r( |0 i
5 r+ l% K, E% J4 {
网上找来了不少的文章, 方法好像只有一种wglUseFontOutlines把每次输出串用到的字符一个一个地转换到GB2312然后glGenLists显示glCallLists再glDeleteLists, 我花了近一个小时才把那老兄的代码从近70行U到50行, 干掉没用的变量传递, 沉思...觉醒... 沉睡... 有觉醒... 直到放弃...3 C% f" {- p8 v
4 B- `2 ~* k! r3 m1 W# h我用了一种比较'简陋'的方法取而代之, 前提是字符串必须是unicode, 如果编译器不支持, 还要弄个UNICODE支持进来(我是没弄过滴, 只会摆弄VC8).
$ S1 Q+ A1 _- T" e
, W/ ]& j& i; ?% C; k. a4 p由于unicode的中日韩编码范围在0x3000-0x9fff范围内,因此我试着将FONT_LIST_SPACE增大到了40960-32(因为0x9fff是40959, 空格以前的字符不要, 所以时40960-32). 这样虽然有不少的list空间被浪费了(至少浪费了0x3000=12288字节), 但起码下面的程序终于能正常显示UNICODE中文了.
4 a4 X, [. Z9 W! j) C- _+ a& g! i2 z: G$ [1 z
我把整个过程封在三个函数中:BuildFontList, PrintString, FreeFontLists. 如下,注意引入类型和global
' V' S( }5 |4 O6 m& Y: g+ L( `8 r2 Y# ~9 h- G0 U$ \
- V, @& ?9 E' N- @5 x, f) p$ ~#include "tchar.h"
' F+ p* G" ~$ |2 B; g5 T! s#define FONT_LIST_SPACE 40960-32
- x. \( U( [* ^3 b( I
g8 M4 E- z6 m8 O7 u2 O+ h#ifdef UNICODE' F' l8 J! s' k
typedef wchar_t tchar;9 I% c1 T, \. L/ x L+ K, R! @
#else
7 f6 H: p/ U5 S% N4 |typedef char tchar;1 t. q2 D; H. E( I! l7 e: c
#endif6 `# [) W+ F M+ [5 L
typedef unsigned int uint;; o9 w0 l; M0 U1 z; @- m
! Q- t, _; s# b( f( S c
7 `# P& [" w9 sHGDIOBJ hobj;. M* `. F1 o$ ~$ K2 G/ _7 u0 E
: X S. w+ b+ W4 R4 G/ duint BuildFontLists(tchar* font, int size) {% o6 t% ]% P$ C; X# M3 i
HFONT hfont;( S7 p4 e: O6 K. C+ }- h
uint base;
. Y3 C0 r- J2 r: {$ w4 `; Q
0 o S1 y% b' j if(!_tcsicmp(font,_T("symbol"))) {1 j7 l: ^5 O5 |4 D
hfont = CreateFont(size, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
8 c# X. H3 n- A2 X2 g! U4 X4 W' i! t SYMBOL_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,! s, s) U ]1 h! N& N
ANTIALIASED_QUALITY, FF_DONTCARE|DEFAULT_PITCH, font);- Q* B6 L( W9 G. l; T; J4 s
}else {' a) s4 p9 [ i8 Q |' c, D' Z
hfont = CreateFont(size, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
8 J- r+ x1 K: g8 _+ s0 S ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
! E% f3 i4 X9 o0 R( l. D ANTIALIASED_QUALITY, FF_DONTCARE|DEFAULT_PITCH, font);
S" f* Q( D" L! ^ //这里使用ANSI_CHARSET/GB2312_CHARSET似乎并无影响 //后来发现没影响是因为simsun.ttc字体文件本身的原因
5 x5 a4 |1 B- f/ B1 Z }# `, ^$ H- i6 i
if(!hfont) {
' K1 I1 T$ |) B8 B& {1 a) X return 0;- O& C, ]) ^" i1 ~" \
}* |6 I. h' k7 c& ~6 p" U- r0 N
, Z& A3 K$ L; o" ~ S7 s4 f
hobj = SelectObject (wglGetCurrentDC(), hfont);
6 y1 |/ ^0 f3 e$ l4 d' H base = glGenLists(FONT_LIST_SPACE);$ d9 r( B( H4 k
wglUseFontBitmaps (wglGetCurrentDC(), 32, FONT_LIST_SPACE, base);
- M: }; o. a6 { return base;: P ^9 s* a8 @% w5 r# L" _$ m
1 I/ v9 Q7 U# U+ t# q4 v1 G& c
}* ^7 ^: r8 B( B: q
void PrintString(uint base, tchar *s) {
3 r8 z$ V0 D9 }& }$ N if(!base || !s || !*s) {: P; ^4 y7 v, [9 J& e; f- Y
return;, @( F, I9 U9 u7 U- ^" R3 p. R- T
}3 C% u& A* v. i& u N% C0 ~7 I( C& w
3 f0 V9 o! R9 _/ q
glPushAttrib(GL_LIST_BIT);
d* `, G$ x! ^) e glListBase (base-32);1 R4 A- a( Y' [
glCallLists (_tcslen(s), GL_UNSIGNED_SHORT, s);
" U+ T; p# @8 z8 q/ O* t glPopAttrib();
# T2 c8 C* `+ d( O- w( h}2 Y6 p$ L t# ?$ n* M. | s
4 C0 i# F: G" j/ C0 H5 g8 w1 R( |void FreeFontLists(uint base) {
- P: z* K! e A- P: m! P if(base) {. m( n) E, m* l( B& y/ N$ S
glDeleteLists(base, FONT_LIST_SPACE);
2 j- t9 r5 v8 O" W5 ]- V3 p DeleteObject(hobj);2 D3 w4 M/ M" j
}( i4 c. S3 \' m/ d5 W
}+ |* P) r2 t' @ }8 ]# B
- s7 K. ]* Y$ }( Q. Z
按以下步骤使用: 1.在OGL建立时调用一次, \' u3 u3 Q6 ~+ x
( ^1 e. Q% J% r2 ?
0 _6 |1 n9 ] L8 [( H+ T- ffont_list = BuildFontLists(_T("新宋体"), 12); //建立12磅的新宋体显示列表到font_list;
6 t3 A- e9 X# j( q K+ D% ~5 u& a1 e //原型 uint font_list;
; E, T: k H$ ^4 q9 T1 o3 h5 `6 ~4 Q
2.在OGL中绘制字体时:1 c& r" o' z# ~0 E% B0 [
5 K% V0 n; a, u3 z% J$ T$ S( J
- l m. P* W' I$ AStartOrtho(); //进入正射投影
* H6 E- z+ x6 UDrawSomthingLikeGUI();
, Y! j6 [$ q, N! G9 y. u/ F1 XglWindowPos2f(cx, cy);; Q) b" c6 D$ y& z
PrintString(font_list, _T("如果你的程序可以在渲染时切到桌面,"));
. R& r* I x- F3 D4 C$ PglWindowPos2f(cx, cy-=12);
+ H! j+ [, h I5 { @8 v3 i* P$ CPrintString(font_list, _T("建议你观察下现在的内存占用量,"));, O! n" W' _: _6 F
glWindowPos2f(cx, cy-=12);
1 a. o& L2 p/ n7 ~9 O1 APrintString(font_list, _T("我这里竟有13mb之多...."));
* n: B' n3 z' `DrawUICursor();
8 S! \9 g& X5 t) XEndOrtho(); //离开正射投影(恢复透视投影)
1 b* \8 z- J$ u' I3.OGL关闭时调用一次/ E5 c; n6 ]) H- i5 w
/ U+ g# ~+ Y2 M1 m& s! e% _! T" W6 }1 C s. J. b
FreeFontLists(font_list); //即可释放掉显示列表,在我的机器上,整个退出过程需要大概2秒左右的时间,fuck!
, R5 [8 j( b1 I$ {# [% O. P
2 Z x Z0 H- ]0 f小结: 尽管中文显示出来了,但是毕竟完美离我还很遥远。 由于是纯位图,因此不能简单地缩放拉伸;虽然效率上要比用wglUseFontOutlines高了不少,内存占用也稍低,但仍然不够低;5 y) l+ }* }8 d$ ]4 @: g
' m( D. O. d- {; w5 h# g
如果能把一个套外观合适的字体生成到一个纹理文件中(比如16x16点阵的所有UNICODE可见字符),然后分段映射到UNICODE字符编码上,再利用矩形贴图,处理速度应当理想一些,而且没了显示列表的一些东西,我想内存占用也最多不超过1mb(我想实际上512kb就足够了)。
+ t! B7 K. C$ I( Y, d3 `: |" T2 K1 z, A2 x% ?' ~- t: r
以上代码的运行,由于引入了HGDIOBJ和wglUseFontBitmaps和glGenLists(40960),内存占用会增加近10mb,不知道是哪来的那么多东西,希望改用纹理后内存占用会好些... |