OpenGL系统设计-位图 字体(6) 汉字TrueType字体
2009-11-05 21:03
435 查看
1.1 中文字体
在上一节的程序运行中可以看到,包括Wingdings字体在内的9种字体都正确显示,唯独第10种字体“宋体”虽然可以显示英文字符,但却无法显示中文字符。这是因为我们的glBuildFont函数仅仅是为英文设计的,它针对每种英文字体生成了128个显示列表,显示某一个字符时只需要调用对应的显示列表即可。
汉字字符和英文字符不同的是,每一个汉字占用两个字节,和汉文、日文都是双字节字符集。并且汉字总数超过8000个,如果每一个汉字也使用一个显示列表来保存的话,资源的消耗是惊人的。
实际上即便能够承受巨大的资源消耗,直接利用wglUseFontBitmaps和wglUseFontOutlines还是无法显示汉字。其实,这两个函数都有UNICODE版本wglUseFontBitmapsW和wglUseFontOutlinesW,目的就是为了处理包括汉字在内的国际所有字符。但是不论在Window 9x/XP还是Windows NT/2000,使用UNICODE版本来处理汉字还是无法实现。
再进一步,我们可以看到,在微软最新的MSDN中,或者在微软的网站上都可以找到如下的信息:
PRB: wglUseFontOutlines Does Not Handle DBCSPSS ID Number: Q228099
Article Last Modified on 10-29-2001
--------------------------------------------------------------------------------
The information in this article applies to:
Microsoft Win32 Application Programming Interface (API)
Microsoft Windows 98
Microsoft Windows NT Server 4.0
Microsoft Windows NT Workstation 4.0
Microsoft Windows XP Home Edition
Microsoft Windows XP Professional
--------------------------------------------------------------------------------
Symptoms
On Windows 98, the OpenGL function wglUseFontOutlines does not work with DBCS or UNICODE strings. On Windows NT, UNICODE strings work; however, DBCS strings do not.
Cause
DBCS strings are not handled by the glCallLists function, which is used to draw the display list built by wglUseFontOutlines. The reason is that a DBCS string contains characters that are one byte or two bytes each depending on the high byte. Because DBCS strings are not a consistent length, glCallLists does not parse them.
以上信息说明了DBCS字符串包含的字符可能是单字节的字符也可能是双字节的字符,这依赖于第一个字节。由于DBCS字符串长度的不确定性,glCallLists根本就不对其进行分析,因此,wglUseFontOutLines不能直接处理双字节字符,包括中文、日文、韩文。简单来说,这是WGL的一个BUG,而且微软也好像没有要解决的意思,因此如果需要在自己的应用程序中显示汉字,就必须自己想办法解决。
我们的办法是根据双字节字符集DBCS字符串中每一个字节确定是否双字节字符,针对双字节单独处理,每一个汉字字符生成一个显示列表,显示完毕后就把显示列表释放掉,这样就不会有大量资源消耗了。下面是使用wglUseFontOutLines来实现汉字显示的代码。
/*
* szText:要显示的字符串
* strFontName:字符串的字体
*/
void glPrintCC(char *szText, LPSTR strFontName)
{
int i, j, ich;
HFONT hFont;
hFont = CreateFont(
0, //缺省高度
0, //缺省宽度
0, //指定移位向量和设备X轴之间的角度,缺省值
0, //字符的基线和设备X轴之间的角度。缺省值
FW_NORMAL, //字体的权值,
FALSE, //是否斜体
FALSE, //是否有下划线
FALSE, //是否有删除线
GB2312_CHARSET, //汉字字符集
OUT_TT_PRECIS, //输出精度
CLIP_DEFAULT_PRECIS, //裁减精度
ANTIALIASED_QUALITY, //输出质量
FF_DONTCARE|DEFAULT_PITCH, //字体间距和字体族
strFontName); //字体名称
SelectObject(g_hDC,hFont);
int length = strlen(szText);
//字符串长度为空就返回
if(length<1)
return;
GLYPHMETRICSFLOAT *gmf;
gmf = new GLYPHMETRICSFLOAT[length];
if(!gmf)
return;
//显示列表
BYTE *CCList;
CCList = new BYTE[length];
if(!CCList)
{
delete [length]gmf;
return;
}
char cch;
//生成显示列表集
GLuint base= glGenLists(length);
i=0; j=0;
for(i=0, j=0; i<strlen(szText);)
{
if (IsDBCSLeadByte(szText[i])) ///判断是否为双字节
{
ich=szText[i];
ich=(ich<<8)+256; //256为汉字内码“偏移量”
ich=ich+szText[i+1];
i++;i++;
wglUseFontOutlines(
g_hDC, //字体设备上下文DC
ich, //要转换为显示列表的第一个字符
1, //要转换为显示列表的字符数
base+j, //显示列表的基数
0.0f, //指定与实际轮廓的最大偏移量
0.1f, //在Z轴负方向的值
WGL_FONT_POLYGONS, //指定显示列表线段或多边形
&gmf[j]); //接受字符的地址
CCList[j]=j;
j++;
}
else //单字节字符
{
cch=szText[i];
i++;
wglUseFontOutlines(
g_hDC,
cch,
1,
base+j,
0.0f,
0.15f,
WGL_FONT_POLYGONS,
&gmf[j]);
CCList[j]=j;
j++;
}
}
glPushAttrib(GL_LIST_BIT);
glListBase(base);
//显示字符串
glCallLists(strlen(szText),GL_UNSIGNED_BYTE, &CCList[0]);
glPopAttrib();
//显示完毕后删除显示列表
glDeleteLists(base, length);
DeleteObject(hFont);
delete []gmf;
delete []CCList;
}
int glInit()
{
//启用阴影平滑(Smooth Shading)。
glShadeModel(GL_SMOOTH);
glClearColor(1.0f, 1.0f, 1.0f,0.0f);
//设置深度缓冲
glClearDepth(1.0f);
//启动深度测试
glEnable(GL_DEPTH_TEST);
//深度测试的类型
glDepthFunc(GL_LEQUAL);
//进行透视修正
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glCreateAllFonts();
//如果将GL_FIL改成GL_LINE,则显示的汉字就是空心字
glPolygonMode(GL_FRONT_AND_BACK, GL_FIL);
return TRUE;
}
void glMain()
{
static float angle = 0.0;
Sleep(300);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); //加载单位矩阵
glTranslatef(-8.0f, 3.0f, -15.0f);
glColor3f(0.0f, 0.0f, 0.0f);
glPrintCC("楷体字体", "楷体");
glPrintCC("隶书字体", "隶书");
glPrintCC("仿宋字体", "仿宋");
glPrintCC("宋体字体", "宋体");
glTranslatef(-16.0f, -2.0f, 0.0);
glPrintCC("华文彩云", "华文彩云");
glPrintCC("华文行楷", "华文行楷");
glPrintCC("华文新魏", "华文新魏");
glPrintCC("华文细黑", "华文细黑");
glTranslatef(-15.5f, -2.0f, 0.0);
glPrintCC("黑体字体", "黑体");
glPrintCC("幼圆字体", "幼圆");
glPrintCC("方正舒体", "方正舒体");
glPrintCC("方正姚体", "方正姚体");
glTranslatef(-15.0f, -2.0f, 0.0);
glScalef(2.0f, 2.0f, 2.0f);
glPrintCC("文鼎广告体繁", "文鼎广告体繁");
glTranslatef(-6.0f, -1.5f, 0.0);
glPrintCC("文鼎海报体繁", "文鼎海报体繁");
SwapBuffers(g_hDC);
}
程序运行结果如图8-7所示,我们需要的汉字都显示出来了。
图8-7 汉字TrueType字体
相关文章推荐
- OpenGL系统设计-位图 字体(3) 汉字显示
- OpenGL系统设计-位图 字体(5) TrueType字体
- OpenGL系统设计-位图 字体(1)
- OpenGL系统设计-位图 字体(2)
- OpenGL系统设计-位图 字体(4) 读写像素
- windows visual studio 基于openGL的粒子系统设计
- OpenGL系统设计-全屏模式(1)
- OpenGL系统设计-粒子系统(2)
- OpenGL系统设计-反走样
- OpenGL系统设计-前言
- OpenGL系统设计-2 第一个OpenGL应用
- OpenGL系统设计-光照与材质(5)
- OpenGL系统设计
- OpenGL系统设计-高级3D模型接口之MD2模型(2)
- OpenGL系统设计-扩展建模(6)
- OpenGL系统设计-全屏模式(2)
- OpenGL系统设计-扩展建模(1)
- OpenGL系统设计-1.1什么是OpenGL
- 汉字输入教学系统中词组切分方法的设计
- OpenGL系统设计-高级3D模型接口之MD2模型(3)