原文6 R$ N& P) ?/ X6 j6 ~" o
http://tsuui.is-programmer.com/a ... st-under-win32.html, {1 x* q! T; x$ z5 a4 \( N
& y% n2 w$ F9 z) q0 d9 t有了FreeType2,这些东西都是历史了....这文还是留着吧, 以后参考
9 o) _4 d& s5 n8 P( ?6 J
" M$ B% w- f3 ^* v网上找来了不少的文章, 方法好像只有一种wglUseFontOutlines把每次输出串用到的字符一个一个地转换到GB2312然后glGenLists显示glCallLists再glDeleteLists, 我花了近一个小时才把那老兄的代码从近70行U到50行, 干掉没用的变量传递, 沉思...觉醒... 沉睡... 有觉醒... 直到放弃...) B/ V r }/ B1 ]( ^( c
) r( s# |* |: u1 U我用了一种比较'简陋'的方法取而代之, 前提是字符串必须是unicode, 如果编译器不支持, 还要弄个UNICODE支持进来(我是没弄过滴, 只会摆弄VC8).5 I$ q* Z5 o" B% c8 Q9 J. V6 a# C
. R& k3 m% T1 X& d0 \* V
由于unicode的中日韩编码范围在0x3000-0x9fff范围内,因此我试着将FONT_LIST_SPACE增大到了40960-32(因为0x9fff是40959, 空格以前的字符不要, 所以时40960-32). 这样虽然有不少的list空间被浪费了(至少浪费了0x3000=12288字节), 但起码下面的程序终于能正常显示UNICODE中文了.; q0 j8 i5 A, p3 q" Z% G8 r6 m/ t
d9 N9 O2 f k. A# ~* q& g
我把整个过程封在三个函数中:BuildFontList, PrintString, FreeFontLists. 如下,注意引入类型和global) s; n& j: t5 M6 L" S7 h& ~/ h# Z! I; `
% c& r* G& a, }8 X9 [" i4 n' A; s# r
1 |. A5 ~) w8 i#include "tchar.h"1 ?" u& t8 x' h+ y; W; f$ W
#define FONT_LIST_SPACE 40960-32
/ l) B( k; ?2 b+ N + e4 {+ S8 U5 B
#ifdef UNICODE
& d( s9 _6 m* ?5 @: {9 ?9 Itypedef wchar_t tchar;
) r$ t* M! p6 W: c#else7 r1 V4 x* d& v
typedef char tchar;
% M; _7 o9 U; W b7 a#endif# Q- x) I' Z4 r2 [
typedef unsigned int uint;7 Y; i% r! V! v, k3 D7 ^
$ b8 r0 `; t7 G / {* b- W- h9 ?& W- d# s$ a
HGDIOBJ hobj;
- A0 P# D' s9 O6 G% T% W
: `1 V+ o; W5 W$ x4 y7 guint BuildFontLists(tchar* font, int size) {& k4 }' j$ m6 {% N# ]# L
HFONT hfont;1 T2 \* v) C4 x1 o! T' Y
uint base;) @2 S* i/ ^/ V3 [ M" i2 l* Y
+ B( Z& B1 X& @
if(!_tcsicmp(font,_T("symbol"))) {$ O" U2 x1 U/ ^. q
hfont = CreateFont(size, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
5 [. \, `- n; M; S' J- l7 j SYMBOL_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
F" D0 ?: G/ z9 L8 U$ R ANTIALIASED_QUALITY, FF_DONTCARE|DEFAULT_PITCH, font);3 K0 k* X8 X% C0 j. f* q( A/ R! Q/ {
}else {
- E7 f4 j0 S1 i hfont = CreateFont(size, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
& r& h$ S8 D* _1 g! p7 U. i ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
' G" o* T. B( n& Q1 Y/ \, O ANTIALIASED_QUALITY, FF_DONTCARE|DEFAULT_PITCH, font);
; ^3 W4 [; g* g* ~ //这里使用ANSI_CHARSET/GB2312_CHARSET似乎并无影响 //后来发现没影响是因为simsun.ttc字体文件本身的原因
3 K( G# @7 {, @( m8 O; I; g' i }( U# k2 A1 f! Z
if(!hfont) {
6 g' s. B" k; X; e9 `( h% U return 0;2 s7 f7 z6 N; r2 a! _8 a4 q
}$ f, e5 P' Z' x6 ` Z) R
% i o% [( H% \' ]7 U7 F2 a0 Q
hobj = SelectObject (wglGetCurrentDC(), hfont);
6 D* p; N! |& y: J. q' u J! R base = glGenLists(FONT_LIST_SPACE);
& j0 y4 ?" v; Q- _5 w. U: n" d2 T wglUseFontBitmaps (wglGetCurrentDC(), 32, FONT_LIST_SPACE, base);
- n" c! B2 `# e- f6 D% o return base;
8 V4 F/ H! T2 S* V" D( n7 I
% ~& }$ u5 B3 U7 Y! s5 |. @: p}7 D, g1 @9 j$ {% a
void PrintString(uint base, tchar *s) {+ y: V0 X* n* k6 h% X
if(!base || !s || !*s) {" k' p9 X' e3 _% l& Y" {3 l* O
return;5 b* |' H2 A# d& y
}
- Y/ S* d: ^3 g
( z [) G3 C5 R3 E8 ?. s2 i s glPushAttrib(GL_LIST_BIT);$ ~2 O d6 \6 E, _* a
glListBase (base-32);
& y. P! n& n; g) V4 l glCallLists (_tcslen(s), GL_UNSIGNED_SHORT, s);) N9 I! u) i* S9 s
glPopAttrib();8 M) V2 [+ Y: W, h" {
}( l9 t0 V, s C" D( V
1 J+ Y. `1 R# M3 p, q) L/ K
void FreeFontLists(uint base) {. c. s; Y6 {! k; K$ k
if(base) {$ U5 T3 q3 r7 h) P9 F
glDeleteLists(base, FONT_LIST_SPACE);2 P" O( L" O" [1 [4 V9 J
DeleteObject(hobj);: D% u3 ^7 d) v
}
4 ] B4 t+ Z7 o' i9 b) d' F( Y}
0 f9 s9 z& @5 v: _5 _6 Q
1 b" M/ ~5 e3 l4 }按以下步骤使用: 1.在OGL建立时调用一次. |4 f4 S& b: r
4 Y' {3 W$ h: q3 ~: V0 N, j' K0 H6 @
) y; L! n( Q6 Z6 F8 yfont_list = BuildFontLists(_T("新宋体"), 12); //建立12磅的新宋体显示列表到font_list;
f, v$ A3 c- E( ` //原型 uint font_list;
) Z' J+ C) X% q+ o) J$ `
- c @" J& P; W# c0 h2.在OGL中绘制字体时:2 @, u* L- E' L+ m+ F9 {$ r8 k
& m _( l' v5 D1 C
1 g# H. E; o0 @' o0 ~5 F$ k
StartOrtho(); //进入正射投影
( X4 {) G$ ]0 B& I9 }! aDrawSomthingLikeGUI();* F9 a! @+ d; d' z% `1 ~8 B
glWindowPos2f(cx, cy);
! h0 t: W1 ^4 e" v9 {7 J! }PrintString(font_list, _T("如果你的程序可以在渲染时切到桌面,"));/ q+ Y2 a5 p( T' x* m: l
glWindowPos2f(cx, cy-=12);2 E2 `1 J6 u6 P! r
PrintString(font_list, _T("建议你观察下现在的内存占用量,"));
- J* R6 }" k/ ]% zglWindowPos2f(cx, cy-=12);1 `2 ?+ D7 v8 U2 j3 U/ }7 a* V
PrintString(font_list, _T("我这里竟有13mb之多...."));
2 {# T0 W0 k8 i$ \0 Q% y: w. o" `DrawUICursor();5 l8 R. t3 P K3 J% @# G
EndOrtho(); //离开正射投影(恢复透视投影)5 v: [! i2 T2 u* c; Q5 m
3.OGL关闭时调用一次
' b' x, D8 V$ F( @' J+ J4 h
4 Z" Q8 ^ e/ @; w9 E* F: B5 j( U2 ?$ {$ I( N7 ^! m
FreeFontLists(font_list); //即可释放掉显示列表,在我的机器上,整个退出过程需要大概2秒左右的时间,fuck!
( Z; y4 n4 {% m6 Y6 y/ g( ^+ {4 c5 h2 z7 M1 I$ q/ G N& c' {
小结: 尽管中文显示出来了,但是毕竟完美离我还很遥远。 由于是纯位图,因此不能简单地缩放拉伸;虽然效率上要比用wglUseFontOutlines高了不少,内存占用也稍低,但仍然不够低;3 {. ~0 i/ |; P, C( I( U ^
( \4 R6 T+ Y: S, k- B/ G# m
如果能把一个套外观合适的字体生成到一个纹理文件中(比如16x16点阵的所有UNICODE可见字符),然后分段映射到UNICODE字符编码上,再利用矩形贴图,处理速度应当理想一些,而且没了显示列表的一些东西,我想内存占用也最多不超过1mb(我想实际上512kb就足够了)。9 S1 w) R( O' P O- ^( {5 q- q) g% W
' s: w' [# |9 L) F4 E以上代码的运行,由于引入了HGDIOBJ和wglUseFontBitmaps和glGenLists(40960),内存占用会增加近10mb,不知道是哪来的那么多东西,希望改用纹理后内存占用会好些... |