原文, C+ o) u. ~/ f2 j- u
http://tsuui.is-programmer.com/a ... st-under-win32.html
3 M- \, R* C/ G# P7 @# B5 s
( i) P8 h! q' @3 a+ O8 \7 o2 `% Z有了FreeType2,这些东西都是历史了....这文还是留着吧, 以后参考: k2 p0 n2 Y: j$ R4 B
! ~* e7 l( D1 N- M% a
网上找来了不少的文章, 方法好像只有一种wglUseFontOutlines把每次输出串用到的字符一个一个地转换到GB2312然后glGenLists显示glCallLists再glDeleteLists, 我花了近一个小时才把那老兄的代码从近70行U到50行, 干掉没用的变量传递, 沉思...觉醒... 沉睡... 有觉醒... 直到放弃...! W$ ]! o8 T% o- m
7 {: S# [8 v0 z9 `" [; J我用了一种比较'简陋'的方法取而代之, 前提是字符串必须是unicode, 如果编译器不支持, 还要弄个UNICODE支持进来(我是没弄过滴, 只会摆弄VC8).
i: g# ^7 Z1 S; `5 r5 f6 v) o
% {/ Y4 ?& y9 t8 C: O由于unicode的中日韩编码范围在0x3000-0x9fff范围内,因此我试着将FONT_LIST_SPACE增大到了40960-32(因为0x9fff是40959, 空格以前的字符不要, 所以时40960-32). 这样虽然有不少的list空间被浪费了(至少浪费了0x3000=12288字节), 但起码下面的程序终于能正常显示UNICODE中文了.2 {5 k+ o4 T, B8 U* d
( H# Z3 D2 S* E1 y# K我把整个过程封在三个函数中:BuildFontList, PrintString, FreeFontLists. 如下,注意引入类型和global
! C/ H3 ?- P0 g% P. z5 x6 Z/ \4 T9 X) e
, ^% n3 m& B) l. w' p#include "tchar.h"
1 t, r9 C2 @0 U1 l2 _#define FONT_LIST_SPACE 40960-32
' L: {% U" v+ p- ?7 i1 Z " B& e$ x+ x: }8 N) |+ ?+ k( n _
#ifdef UNICODE/ q5 @" F' E$ p& B2 I/ s
typedef wchar_t tchar;* M& y8 {: X5 {3 E3 Y
#else L2 J$ Z9 ?, P8 o# F
typedef char tchar;6 |6 U" M0 Q% z. j% X& G3 T! h. h
#endif% ?0 y. ~2 u$ f6 L+ A
typedef unsigned int uint;2 T) H; ^ l8 z+ w5 l( C
+ P) [) i6 s$ p7 S+ L . c! ?' p; r# |$ \' d
HGDIOBJ hobj;
3 h8 U j( `5 r! v6 q, a
4 N' p' E O* s0 ~. tuint BuildFontLists(tchar* font, int size) {
/ i6 J3 a" a7 ^. q P HFONT hfont;
1 u1 ]9 {! {3 W \) N5 M uint base;
0 f- |( s# P6 @" n( q
5 Z( c1 V2 s! K2 D+ u' e6 z if(!_tcsicmp(font,_T("symbol"))) {4 Z* i/ t" L5 Q
hfont = CreateFont(size, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,2 a. Y6 E# D- p0 s% ]" J9 O
SYMBOL_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
' o6 j" k/ ]- z. N' |2 O# ^ ANTIALIASED_QUALITY, FF_DONTCARE|DEFAULT_PITCH, font);( D5 [. K- M* A. X3 G
}else { U/ A$ l9 t k, }
hfont = CreateFont(size, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
( t( d5 ~# n$ ~( P: ]1 a3 B' H ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,1 i$ b+ e! i& d' ?5 u7 Z8 O
ANTIALIASED_QUALITY, FF_DONTCARE|DEFAULT_PITCH, font);
3 @4 t3 K2 J1 [7 {/ G8 ], Z //这里使用ANSI_CHARSET/GB2312_CHARSET似乎并无影响 //后来发现没影响是因为simsun.ttc字体文件本身的原因
; q( c" e: B U T }
& x7 g- @# Y6 y+ C6 p2 k- T if(!hfont) {
7 _7 o8 w+ z0 D L return 0;/ I1 A2 b4 p1 |
}
3 \8 O: ?0 z* `8 d( o4 | 9 M* X) C+ X9 m' m
hobj = SelectObject (wglGetCurrentDC(), hfont);
5 u& Y4 p$ ?/ k) \) U ? base = glGenLists(FONT_LIST_SPACE);
. u3 N' q: I9 f% U' W. F# g# j wglUseFontBitmaps (wglGetCurrentDC(), 32, FONT_LIST_SPACE, base);% `, q2 O* {/ A8 C2 d' F
return base;) ~: j$ ~! T8 y2 o$ W
3 a6 L4 k/ G6 w" e}
}! d% b* e7 o; |# rvoid PrintString(uint base, tchar *s) {
! H/ b2 O ?4 J) y) @( l if(!base || !s || !*s) {+ F% _5 P. b4 Y+ t9 X+ J
return;
8 [$ \1 d; {, a" f9 O }4 g5 f0 o9 Q3 t7 x5 Z0 ?
( w$ @$ f, @# a. X5 n7 X
glPushAttrib(GL_LIST_BIT);
, Z% M! [9 @, p# J ]3 F+ W glListBase (base-32);( O7 I7 s0 D, Q
glCallLists (_tcslen(s), GL_UNSIGNED_SHORT, s);. p' r6 _6 W# _6 S- |. U1 [
glPopAttrib();
0 \, h2 k4 Y, r9 H; \}
# r0 ^/ }% `( ^; M& y. O 7 b; q+ W8 s% c
void FreeFontLists(uint base) {
2 V% f, u- H& K/ S3 L) J# ]9 b if(base) {5 {2 E4 ^+ r7 m4 J6 w
glDeleteLists(base, FONT_LIST_SPACE);" h7 N8 Q, \" H
DeleteObject(hobj);, O% ^( G' R" f; B4 |
}8 b- |# O7 I* S
}
" U8 ]* z7 R; L+ N* j& L3 S, n5 Y, S0 X; E: C5 Z5 Q S e
按以下步骤使用: 1.在OGL建立时调用一次
+ V0 f) o6 M- Q0 R" |4 D7 |/ h7 S/ z% D6 T
0 \- R3 J9 r5 m( l, j' \% Efont_list = BuildFontLists(_T("新宋体"), 12); //建立12磅的新宋体显示列表到font_list;
; ?4 r9 ^# c8 Z, D //原型 uint font_list;
8 Z8 k, l, H# H+ y1 V: ` }; C7 w) M6 e5 I
2.在OGL中绘制字体时:
0 G0 x: R$ _" k! S: G4 k- B9 M) A$ ~5 U$ r
& N; J1 P( v7 o1 k2 G5 K' gStartOrtho(); //进入正射投影: ^' L h6 k$ Y) A/ ~' y k
DrawSomthingLikeGUI();/ z5 C# J2 s8 F( ~; v* p6 p+ |
glWindowPos2f(cx, cy);
; ]) @0 y- F' t& c2 O# PPrintString(font_list, _T("如果你的程序可以在渲染时切到桌面,"));
* ?% S2 Z' t. g+ u6 d/ \glWindowPos2f(cx, cy-=12);
9 | E. G# G9 b% \& CPrintString(font_list, _T("建议你观察下现在的内存占用量,"));
! w+ D' J5 |. d4 c# @ v1 lglWindowPos2f(cx, cy-=12);
* E1 P; u- }9 f/ w& H ~PrintString(font_list, _T("我这里竟有13mb之多...."));
9 K6 `6 `) l/ E- Z) VDrawUICursor();$ {/ O! _2 q9 ~- S
EndOrtho(); //离开正射投影(恢复透视投影)* F- \3 c+ J1 v8 D) v. V+ |
3.OGL关闭时调用一次
; r# i% J2 _; x" k4 m. {& y* e5 N% s* A6 Y
3 B9 V% j6 H+ i( K4 i2 XFreeFontLists(font_list); //即可释放掉显示列表,在我的机器上,整个退出过程需要大概2秒左右的时间,fuck!2 g/ B# p% k8 v$ v
7 z( w, J1 c( N' H& n6 m小结: 尽管中文显示出来了,但是毕竟完美离我还很遥远。 由于是纯位图,因此不能简单地缩放拉伸;虽然效率上要比用wglUseFontOutlines高了不少,内存占用也稍低,但仍然不够低;+ Q4 c2 ` h/ m$ X
& B& G$ I* i2 S+ E( N
如果能把一个套外观合适的字体生成到一个纹理文件中(比如16x16点阵的所有UNICODE可见字符),然后分段映射到UNICODE字符编码上,再利用矩形贴图,处理速度应当理想一些,而且没了显示列表的一些东西,我想内存占用也最多不超过1mb(我想实际上512kb就足够了)。
8 Q# o7 Q! h6 a: Z- X$ x# ^3 {' `4 s8 f/ K
以上代码的运行,由于引入了HGDIOBJ和wglUseFontBitmaps和glGenLists(40960),内存占用会增加近10mb,不知道是哪来的那么多东西,希望改用纹理后内存占用会好些... |