OpenGL系统设计-位图 字体(5) TrueType字体

 

  TrueType字体

利用位图的方式来实现文本是一种方式,但是这种方式需要事先知道字符的点阵信息,字符的大小也很难随意更改,字体种类就更无法随意选择了。Windows系统提供了大量的TrueType字体,这是我们字体应用的巨大资源。但是在Windows9xWindows NT/2000系统下,不能在双缓冲的OpenGL应用中直接应用GDI调用来显示TrueType字符。

 

为了能够在OpenGL中使用TrueType字体资源,Win32通过WGL库提供了wglUseFontBitmapswglUseFontOutlines函数来满足需要。两个函数的原型如下:

 

BOOL wglUseFontBitmaps(

  HDC  hdc,         // device context whose font will be used

  DWORD  first,     // glyph that is the first of a run of glyphs to

                    // be turned into bitmap display lists

  DWORD  count,     // number of glyphs to turn into bitmap display

                    // lists

  DWORD  listBase   // specifies starting display list

);

 

BOOL wglUseFontOutlines(

  HDC  hdc,         // device context of the outline font

  DWORD  first,     // first glyph to be turned into a display list

  DWORD  count,     // number of glyphs to be turned into display

                    // lists

  DWORD  listBase,  // specifies the starting display list

  FLOAT  deviation, // specifies the maximum chordal deviation from

                    // the true outlines

  FLOAT  extrusion, // extrusion value in the negative z direction

  int  format,      // specifies line segments or polygons in

                    // display lists

  LPGLYPHMETRICSFLOAT  lpgmf

                    // address of buffer to receive glyph metric data

);

 

两个函数的实质是创建一系列的位图显示列表,当需要显示某一个字符时调用对应的显示列表就可以了,显示列表是基于当前DC选择的字体字型。

wglUseFontOutlines函数还允许设置字符的厚度,因此更多的运用于三维TrueType字符的显示。

hdc 参数表示哪一个设备上下文(DC)中选中的字体用于产生位图显示列表。first 表示在选中的字体中从哪一个字符开始创建显示列表,在此之前的字符将不被创建显示列表。count 表示创建的显示列表的个数。listBase 表示开始的显示列表。

wglUseFontOutlines()函数中的deviation 表示显示的字符与实际轮廓的最大偏移量。deviation取值不能为负数,当deviation0时,表示偏移量等于原始字体的一个设计单位。为了简便起见,我们都将其设置为0extrusion 表示在-Z方向的值,即字符的厚度。format 表示显示列表使用直线段还是多边形,取值分别是WGL_FONT_LINESWGL_FONT_POLYGONSlpgmf 是一个数组指针,数组中的每一个元素都是一个GLYPHMETRICSFLOAT结构,用于接收字符的数据。

TrueType字体是用直线和曲线来定义外轮廓,曲线使用B样条曲线。wglUseFontOutlines函数是通过将生成字型本身的二次B样条曲线分割成直线段来逼近字型原始轮廓,当两者之间误差小于deviation时即认为OK

 

下面我们来使用wglUseFontBitmaps创建一个显示TrueType字体的程序。由于增加的内容较多,我们尽可能把详细的代码列出来,但是象WinMain等完全没有变化的就不列出来了。

 

 

// truetype.cpp

//

//前面一些相同的定义就不列出来了

……

#define MAXFONTNUMBER 256   //暂时最多使用256TrueType字体

GLuint  g_Base[MAXFONTNUMBER];  // 每种字体显示列表集的第一个显示列表

 

//创建字体函数

GLvoid glBuildFont(GLuint *base, int nHeight, DWORD fdwCharSet, LPSTR strFontName);

 

//释放字体资源函数

void glFreeFont(GLuint base);

 

//显示字符串函数

GLvoid glPrint(GLuint base, const char *fmt, ...);

 

//预设的字体显示列表包含不超过128个字符

#define MAX_CHARS   128                                

                               

//定义一个字体结构

struct t_Font

{

    int nHeight;            //字符的高度

    DWORD fdwCharSet;       //字符集

    LPSTR strFontName;      //字体名

};

 

 

//预设程序中使用10种字体

t_Font g_Font[MAXFONTNUMBER]=

{

    {18, ANSI_CHARSET, "Arial"},

    {24, ANSI_CHARSET, "GreekC"},

    {24, ANSI_CHARSET, "Italic"},

    {20, ANSI_CHARSET, "Math A"},

    {16, ANSI_CHARSET, "MS Serif"},

    {18, ANSI_CHARSET, "ScriptC"},

    {16, ANSI_CHARSET, "Symbol"},

    {20, ANSI_CHARSET, "Times New Roman"},

    {24, SYMBOL_CHARSET, "Wingdings"},

    {18, GB2312_CHARSET, "宋体"}

};

 

 

//根据字体的大小,字符集和字体名称创建显示列表

GLvoid glBuildFont(GLuint *base, int nHeight, DWORD fdwCharSet, LPSTR strFontName)

{

    HFONT   hFont;     

    GLuint lBase;

 

    //生成一个包含有MAX_CHARS个显示列表的显示列表集

    lBase = glGenLists(MAX_CHARS);             

   

    //创建一种字体,CreateFont是一个标准的Win32 API

    hFont = CreateFont( -nHeight,           //字体的高度

                0,              //字体的宽度,缺省

                0,              //指定移位向量和设备X轴之间的角度

                0,              //字符的基线和设备X轴之间的角度

                FW_NORMAL,          //字体的权值,

                FALSE,                  //是否斜体

                FALSE,                  //是否有下划线

                FALSE,                  //是否有删除线

                fdwCharSet,             //字符集

                OUT_TT_PRECIS,          //输出精度

                CLIP_DEFAULT_PRECIS,        //裁减精度

                ANTIALIASED_QUALITY,        //输出质量

                FF_DONTCARE|DEFAULT_PITCH,  //字体间距和字体族

                strFontName);               //字体名称

 

 

    SelectObject(g_hDC, hFont);                        

 

    //从第一个字符开始创建共MAX_CHARS个显示列表

    wglUseFontBitmaps(g_hDC, 0, MAX_CHARS-1, lBase);   

    *base = lBase;

}

 

//释放字体显示列表

GLvoid glFreeFont(GLuint base)                                 

{

    glDeleteLists(base, MAX_CHARS);                        

}

 

 

//显示字符串

GLvoid glPrint(GLuint base, const char *fmt, ...)

{

    //字符串

    char        text[256];                         

    va_list     ap;                        

 

    //如果字符串为空就返回 

    if (fmt == NULL)       

        return;        

 

    va_start(ap, fmt);                         

        vsprintf(text, fmt, ap);                   

    va_end(ap);                            

 

    glPushAttrib(GL_LIST_BIT);                         

    glListBase(base);                                  

   

    //调用显示列表,显示字符

    glCallLists(strlen(text), GL_UNSIGNED_BYTE, text); 

    glPopAttrib();                     

}

有关字体处理的预备工作就完成了,下面是主程序对字体的处理,显示在屏幕上。

 

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);

   

    //创建10种字体

    for(int i=0; i<10; i++)

    {

 

        glBuildFont(&g_Base[i],g_Font[i].nHeight, g_Font[i].fdwCharSet,

                g_Font[i].strFontName);

    }

   

    return TRUE;

}

 

 

void glMain()

{

   

    static float angle[10] ;

 

    //延迟300毫秒, 效果更加清楚

    Sleep(300);

 

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();   //加载单位矩阵

    glTranslatef(0.0f, 0.0f, -1.0f);

   

    float r, g, b;

 

    // 每一种字体使用不同的颜色显示

    for(int i=0; i<10; i++)

    {

        angle[i%10] = angle[(i+9)%10] +1.0f;

       

        r = float(cos(angle[i]));

        g = float(sin(angle[i]));

        b = float(cos(2*angle[i]));

 

        glColor3f(r, g, b);

 

        glRasterPos2f(-0.5f, 0.35f-i*0.08);

 

        glPrint(g_Base[i], "OpenGL True Type Font- %s", g_Font[i].strFontName);

 

    }

 

    SwapBuffers(g_hDC);

} 

 

当退出程序时要记得释放掉显示列表。

 

void glShutdown()

{

   

……

    for(int i=0; i<MAXFONTNUMBER; i++)

    {

        if(g_Base[i])

            glFreeFont(g_Base[i]);

    }

 

}

 

程序运行后,可以看到10行“OpenGL True Type Font”字符串都以设定的字体显示,并且不停变换颜色,效果如果8-6所示。

 

8-6   OpenGL TrueType字体

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值