原文' U* F" t+ C7 l" A1 j
http://tsuui.is-programmer.com/a ... st-under-win32.html5 _, j6 c0 C# {- _7 F) p
! E" x1 v$ Q1 c# P9 n+ \有了FreeType2,这些东西都是历史了....这文还是留着吧, 以后参考
: w* J; d8 q5 o7 _5 o5 L% ?7 y6 ]5 r8 m
网上找来了不少的文章, 方法好像只有一种wglUseFontOutlines把每次输出串用到的字符一个一个地转换到GB2312然后glGenLists显示glCallLists再glDeleteLists, 我花了近一个小时才把那老兄的代码从近70行U到50行, 干掉没用的变量传递, 沉思...觉醒... 沉睡... 有觉醒... 直到放弃.../ k* H$ R/ K% E/ m5 _9 o6 q
9 L5 P0 ~# |5 C3 s# h; O/ E3 L2 \( ~我用了一种比较'简陋'的方法取而代之, 前提是字符串必须是unicode, 如果编译器不支持, 还要弄个UNICODE支持进来(我是没弄过滴, 只会摆弄VC8).
+ }$ V9 r- V# C0 l4 J! Y" `- n7 t7 a6 P4 S; N
由于unicode的中日韩编码范围在0x3000-0x9fff范围内,因此我试着将FONT_LIST_SPACE增大到了40960-32(因为0x9fff是40959, 空格以前的字符不要, 所以时40960-32). 这样虽然有不少的list空间被浪费了(至少浪费了0x3000=12288字节), 但起码下面的程序终于能正常显示UNICODE中文了.
7 [. q ]$ @4 R$ Y
: D8 }( T& I! ~) n我把整个过程封在三个函数中:BuildFontList, PrintString, FreeFontLists. 如下,注意引入类型和global
+ F) p% e% B2 J/ U, g1 \) {1 C7 O: ] J& ]9 ?
0 G ]% Z1 C+ H4 R1 [# n) D#include "tchar.h"
5 c; p Q1 _- |1 d! ^1 t, s#define FONT_LIST_SPACE 40960-32
4 s+ t* f% d% r9 ` ; A i: U. m: b K, o% S: @
#ifdef UNICODE1 J- c8 G0 j- C
typedef wchar_t tchar;0 Z3 |! H" ?# J0 j9 j7 Y( b8 V# P
#else
! U9 K$ R# N& Ztypedef char tchar;" ?, t# g% a5 X6 U
#endif1 b+ t& P3 ^$ V X) C
typedef unsigned int uint;% C& }4 N$ e! p% {
7 H) l9 q6 T- S2 W3 W O ) N$ `, S: K, }. B6 e/ I$ k
HGDIOBJ hobj;* A+ c+ h0 I: ?5 B' J
8 ?/ b' B' Z+ m* c3 Q$ z% suint BuildFontLists(tchar* font, int size) {
7 M2 v2 O1 h- Z HFONT hfont;
, c( B/ U+ U: n( z0 l& N uint base;
% k8 z& P1 r H
' u5 Q N6 J) \/ q0 [' r+ Z9 G# H2 Q if(!_tcsicmp(font,_T("symbol"))) { o! R2 Q2 s+ V) [+ R
hfont = CreateFont(size, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,- ^( X J. N: R# C% ~8 S
SYMBOL_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS," m/ u7 N% ~1 n' g4 {
ANTIALIASED_QUALITY, FF_DONTCARE|DEFAULT_PITCH, font);6 s, L: ~* _, M3 z
}else {
( I3 H3 ?0 V7 P/ K hfont = CreateFont(size, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
, X& R; M1 p5 }" s! q, T/ e$ |+ t ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, f6 g- o K) O
ANTIALIASED_QUALITY, FF_DONTCARE|DEFAULT_PITCH, font);
% k. v$ V# H3 L9 S- w //这里使用ANSI_CHARSET/GB2312_CHARSET似乎并无影响 //后来发现没影响是因为simsun.ttc字体文件本身的原因0 g' g9 P" N& a0 o' ^, r5 T5 x
}
7 O. _' \; F0 D* `7 g+ J" |( f6 o0 C if(!hfont) {
/ w& ]0 d" U+ b9 [ return 0;! n7 q& j; k5 l9 c, |& ^0 b5 g
}
6 F) c1 T& ^ a% v% ]7 {* y
7 M! _9 x; C( N2 E# Y) \' Q hobj = SelectObject (wglGetCurrentDC(), hfont);* s) e7 D p0 w# L) _
base = glGenLists(FONT_LIST_SPACE);
$ K7 ?2 C- H5 u wglUseFontBitmaps (wglGetCurrentDC(), 32, FONT_LIST_SPACE, base);
6 `* `% |5 j+ X+ Z' u return base;/ w/ n* g# D, H
_. Z1 ~7 M9 j+ r
}& W4 h, {; C2 V+ b
void PrintString(uint base, tchar *s) {# w c6 b% A/ h. A+ v: U1 E7 W, k" J7 A
if(!base || !s || !*s) {
% l) @( N6 h4 d return;
/ u* {8 T+ r" R. k }
: W9 P1 q/ Q" n/ } 7 [; M8 i2 p0 v3 [% J' s# N
glPushAttrib(GL_LIST_BIT);
- B8 G8 `0 i$ x* m glListBase (base-32);
. [/ q3 |# O: _( g- k- W( x glCallLists (_tcslen(s), GL_UNSIGNED_SHORT, s);
. s$ M+ l/ p7 Y7 @4 v% M& j! a glPopAttrib();* @0 M% l9 X/ }& | ~
}$ Y$ M9 l! b1 h8 _& l
1 Z, |7 t+ l5 V) y: kvoid FreeFontLists(uint base) {
# m e7 ?. f9 X3 B8 ?. a if(base) {! | h8 o% G1 a, G; [3 I
glDeleteLists(base, FONT_LIST_SPACE);, K8 y. P. _! x, N9 h* ]
DeleteObject(hobj);1 \$ ]# q6 ?. z$ z4 e$ ^ b
}
& Z+ I# y- M0 S1 t}
" q! \9 ?' s' j# U$ d& _ `5 J ^0 Z
按以下步骤使用: 1.在OGL建立时调用一次
; b: U! Y9 w# b+ ]7 n' Y8 d
- g; C: K* I3 s3 [! w
$ p! H( ^# B4 z" ]: R! Mfont_list = BuildFontLists(_T("新宋体"), 12); //建立12磅的新宋体显示列表到font_list;. ?" i- v: v0 f2 e5 v$ q
//原型 uint font_list;
8 o! G8 N3 J% q4 c: y/ r" Q% X9 G( t7 ]. i+ x; ~
2.在OGL中绘制字体时:2 ~* j/ o8 E! i% J( Y: t! g# Y
& V$ L& m6 |- i C ^, {; N
% c3 S% j& T5 s: T, S7 t% _) y# J3 ~StartOrtho(); //进入正射投影
* [& z3 A* f7 h) r8 MDrawSomthingLikeGUI();/ D" b3 v! O, M) |: k2 m9 i ^. I
glWindowPos2f(cx, cy);
! ^+ @" N- W6 W# ]& f! JPrintString(font_list, _T("如果你的程序可以在渲染时切到桌面,"));# A! i- D9 [3 C) H1 t- N; q
glWindowPos2f(cx, cy-=12);
' N0 f/ D6 r1 R8 ZPrintString(font_list, _T("建议你观察下现在的内存占用量,")); N8 G3 g8 H! S M5 T! L* i
glWindowPos2f(cx, cy-=12);$ r" M# b7 A K, \' m0 `* d
PrintString(font_list, _T("我这里竟有13mb之多...."));. q8 j; B" U" N- o1 p, s
DrawUICursor();6 C6 a& M! B/ c5 u) M
EndOrtho(); //离开正射投影(恢复透视投影)* _4 w( a$ N+ P7 N% z2 x
3.OGL关闭时调用一次9 V+ r, K0 \2 K# ]1 O3 k' \
. G5 I" e( P$ V- d
3 z6 n' y+ Y6 ]( }4 U9 N. L
FreeFontLists(font_list); //即可释放掉显示列表,在我的机器上,整个退出过程需要大概2秒左右的时间,fuck!
5 L* D4 _, Q+ R9 w* E6 H7 ~7 b# u
) X& L" w5 i7 o% G2 E6 b小结: 尽管中文显示出来了,但是毕竟完美离我还很遥远。 由于是纯位图,因此不能简单地缩放拉伸;虽然效率上要比用wglUseFontOutlines高了不少,内存占用也稍低,但仍然不够低;
% C7 k. O+ z. d: F, i, M* T
: L( w, u) |; L如果能把一个套外观合适的字体生成到一个纹理文件中(比如16x16点阵的所有UNICODE可见字符),然后分段映射到UNICODE字符编码上,再利用矩形贴图,处理速度应当理想一些,而且没了显示列表的一些东西,我想内存占用也最多不超过1mb(我想实际上512kb就足够了)。3 Y6 {3 j1 h, P8 _
9 ^" m$ G9 D4 h! U# x以上代码的运行,由于引入了HGDIOBJ和wglUseFontBitmaps和glGenLists(40960),内存占用会增加近10mb,不知道是哪来的那么多东西,希望改用纹理后内存占用会好些... |