OpenGL FreeType库 概述

http://yarin.blog.51cto.com/1130898/381911

NeHe OpenGL第四十三课:FreeType库

在OpenGL中使用FreeType库

使用FreeType库可以创建非常好看的反走样的字体,记住暴雪公司就是使用这个库的,就是那个做魔兽世界的。尝试一下吧,我只告诉你了基本的使用方式,你可以走的更远。
 
在OpenGL中使用FreeType库

这里是一个快速的介绍,它告诉你如何在OpenGL中使用FreeType渲染TrueType字体。使用这个库我们可以渲染反走样的文本,它看起来更加的漂亮。

动机

这里我将给你两个例子,一个是用WGL的bitmap字体渲染得文字,另一个是用FreeType渲染得文字。
 

使用WGl渲染得文字是一些图像,当你放大它们时看起来如下:


如果你使用GNU的FreeType库(暴雪公司也在它们的游戏中使用这个库),它将看起来更漂亮,如下所示,它具有了反走样:


创建程序

第一步你需要从下面的网站上下载FreeType库:http://gnuwin32.sourceforge.net/packages/freetype.htm

接着在你使用它创建一个新的程序时,你需要链接libfreetype.lib库,并包含FreeType的头文件。

现在我们已经能创建基于FreeType的程序了,但我们还不能运行它,因为我们需要freetype-6.dll文件。
好了,现在我们可以开始编写我们的程序了,我们从13课的代码开始,我们添加两个新的文件"freetype.cpp"和"freetype.h"。我们把和FreeType相关的内容放在这两个文件里。

好了,让我们从freetype.h开始吧。

按惯例我们包含一些需要的头文件
 
#ifndef FREE_NEHE_H#define FREE_NEHE_H
//FreeType 头文件
#include <ft2build.h>
#include <freetype/freetype.h>
#include <freetype/ftglyph.h>
#include <freetype/ftoutln.h>
#include <freetype/fttrigon.h>

//OpenGL 头文件
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>

//STL 头文件
#include <vector>
#include <string>

//STL异常类
#include <stdexcept>
#pragma warning(disable: 4786)

我们将把每个字符需要的信息封装在一个结构中,这样就像使用WGL字体一样,我们可以分别控制每个字符的显示状态。 
  
// 把所有的操作放在名字空间freetype中,这样可以避免与其他函数的冲突namespace freetype
{
// 使用vector和string名字空间
using std::vector;
using std::string;

// 这个结构保存字体信息
struct font_data
{
float h; // 字体的高度
GLuint * textures; // 使用的纹理
GLuint list_base; // 显示列表的值

// 初始化结构
void init(const char * fname, unsigned int h);

// 清楚所有的资源
void clean();
};

最后一件事是定义我们输出字符串的原形: 
  
// 把字符输出到屏幕void print(const font_data &ft_font, float x, float y, const char *fmt, ...);
}

#endif

上面就是FreeType的头文件,下面我们看看怎样实现它 
  
#include "freetype.h"
namespace freetype {

我们使用纹理去显示字符,在OpenGL中纹理大小必须为2的次方,这个函数用来字符的大小近似到这个值。所以我们有了如下的方程: 
  
// 这个函数返回比a大的,并且是最接近a的2的次方的数inline int next_p2 (int a ){ int rval=1; // rval<<=1 Is A Prettier Way Of Writing rval*=2;  while(rval<a) rval<<=1; return rval;}

下面一个函数为make_dlist, 它是这个代码的核心。它包含FT_Face对象,它是FreeType用来保存字体信息的类,接着创建一个显示列表。 
  
// 为给定的字符创建一个显示列表void make_dlist ( FT_Face face, char ch, GLuint list_base, GLuint * tex_base ) {
// 载入给定字符的轮廓
if(FT_Load_Glyph( face, FT_Get_Char_Index( face, ch ), FT_LOAD_DEFAULT ))
throw std::runtime_error("FT_Load_Glyph failed");

// 保存轮廓对象
FT_Glyph glyph;
if(FT_Get_Glyph( face->glyph, &glyph ))
throw std::runtime_error("FT_Get_Glyph failed");

// 把轮廓转化为位图
FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1 );
FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;

// 保存位图
FT_Bitmap& bitmap=bitmap_glyph->bitmap;

}

现在我们已经从FreeType中获得了位图,我们需要把它转化为一个满足OpenGL纹理要求的位图。你必须知道,在OpenGL中位图表示黑白的数据,而在FreeType中我们使用8位的颜色表示位图,所以FreeType的位图可以保存亮度信息。 
  
// 转化为OpenGl可以使用的大小 int width = next_p2( bitmap.width ); int height = next_p2( bitmap.rows );
// 保存位图数据
GLubyte* expanded_data = new GLubyte[ 2 * width * height];

// 这里我们使用8位表示亮度8位表示alpha值
for(int j=0; j <height;j++) {
for(int i=0; i < width; i++){
expanded_data[2*(i+j*width)]= expanded_data[2*(i+j*width)+1] =
(i>=bitmap.width || j>=bitmap.rows) ?
0 : bitmap.buffer[i + bitmap.width*j];
}
}

接下来我们选则字体纹理,并生成字体的贴图纹理 
  
// 设置字体纹理的纹理过滤器 glBindTexture( GL_TEXTURE_2D, tex_base[ch]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
// 邦定纹理
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data );

// 释放分配的内存
delete [] expanded_data;

接着创建一个显示列表,它用来绘制一个字符 
  
// 创建显示列表 glNewList(list_base+ch,GL_COMPILE);
glBindTexture(GL_TEXTURE_2D,tex_base[ch]);

//首先我们向左移动一点
glTranslatef(bitmap_glyph->left,0,0);

//接着我们向下移动一点,这只队'g','y'之类的字符有用
//它使得所有的字符都有一个基线
glPushMatrix();
glTranslatef(0,bitmap_glyph->top-bitmap.rows,0);

// 计算位图中字符图像的宽度
float x=(float)bitmap.width / (float)width,
y=(float)bitmap.rows / (float)height;

//绘制一个正方形,显示字符
glBegin(GL_QUADS);
glTexCoord2d(0,0); glVertex2f(0,bitmap.rows);
glTexCoord2d(0,y); glVertex2f(0,0);
glTexCoord2d(x,y); glVertex2f(bitmap.width,0);
glTexCoord2d(x,0); glVertex2f(bitmap.width,bitmap.rows);
glEnd();
glPopMatrix();
glTranslatef(face->glyph->advance.x >> 6 ,0,0);

//结束显示列表的绘制
glEndList();
}

下面的函数将使用make_dlist创建一个字符集的显示列表,fname为你要使用的FreeType字符文件。 
  
void font_data::init(const char * fname, unsigned int h) {  // 保存纹理ID. textures = new GLuint[128];
this->h=h;

// 创建FreeType库
FT_Library library;
if (FT_Init_FreeType( &library ))
throw std::runtime_error("FT_Init_FreeType failed");

// 在FreeType库中保存字体信息的类叫做face
FT_Face face;

// 使用你输入的Freetype字符文件初始化face类
if (FT_New_Face( library, fname, 0, &face ))
throw std::runtime_error("FT_New_Face failed (there is probably a problem with your font file)");

// 在FreeType中使用1/64作为一个像素的高度所以我们需要缩放h来满足这个要求
FT_Set_Char_Size( face, h << 6, h << 6, 96, 96);

// 创建128个显示列表
list_base=glGenLists(128);
glGenTextures( 128, textures );
make_dlist(face,i,list_base,textures);

// 释放face类
FT_Done_Face(face);

// 释放FreeType库
FT_Done_FreeType(library);
}

下面的函数完成释放资源的工作 
  
void font_data::clean() { glDeleteLists(list_base,128); glDeleteTextures(128,textures); delete [] textures;}

在print函数中要用到下面的两个方程,pushScreenCoordinateMatrix函数用来保存当前的矩阵,并设置视口与当前的窗口大小匹配。pop_projection_matrix函数用来返回pushScreenCoordinateMatrix保存的矩阵。reference manual.  
  
// 保存当前的矩阵,并设置视口与当前的窗口大小匹配inline void pushScreenCoordinateMatrix() { glPushAttrib(GL_TRANSFORM_BIT); GLint   viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(viewport[0],viewport[2],viewport[1],viewport[3]); glPopAttrib();}
//返回pushScreenCoordinateMatrix保存的矩阵
inline void pop_projection_matrix() {
glPushAttrib(GL_TRANSFORM_BIT);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();

我们的print函数和13课的函数非常的像,但在实现上有一些不同。我们实际上是使用2通道的纹理而不是图像。 
  
// 输出文字void print(const font_data &ft_font, float x, float y, const char *fmt, ...)  {          // 保存当前矩阵 pushScreenCoordinateMatrix();                                            GLuint font=ft_font.list_base; float h=ft_font.h/.63f;                                                  char text[256];          va_list ap;          
if (fmt == NULL)
*text=0;
else {
va_start(ap, fmt);
vsprintf(text, fmt, ap);
va_end(ap);
}

// 把输入的字符串按回车分割
const char *start_line=text;
vector<string> lines;
for(const char *c=text;*c;c++) {
if(*c=='\n') {
string line;
for(const char *n=start_line;n<c;n++) line.append(1,*n);
lines.push_back(line);
start_line=c+1;
}
}
if(start_line) {
string line;
for(const char *n=start_line;n<c;n++) line.append(1,*n);
lines.push_back(line);
}

glPushAttrib(GL_LIST_BIT | GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TRANSFORM_BIT);
glMatrixMode(GL_MODELVIEW);
glDisable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glListBase(font);

 float modelview_matrix[16];      glGetFloatv(GL_MODELVIEW_MATRIX, modelview_matrix);
// 下面的代码完成具体的绘制过程
for(int i=0;i<lines.size();i++) {
glPushMatrix();
glLoadIdentity();
glTranslatef(x,y-h*i,0);
glMultMatrixf(modelview_matrix);

//调用显示列表绘制
glCallLists(lines[i].length(), GL_UNSIGNED_BYTE, lines[i].c_str());

glPopMatrix();
}

glPopAttrib();

pop_projection_matrix();
}

}

}

FreeType库我们就写好了,现我们在13课的代码上来做一些修改,当然首先我们需要包含freetype.h的头文件 
  
#include "freetype.h"
  
现在我们就可以调用freetype库绘制字符串了 
  

// 保存我们创建的字体的信息freetype::font_data our_font;
  
接下来使用test.ttf文件初始化字体 
  
our_font.init("Test.ttf", 16);
  
在程序结束时记得释放内存资源 
  
our_font.clean();
  
下面是我们具体的绘制函数 
  
int DrawGLScene(GLvoid)          { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);      glLoadIdentity();          glTranslatef(0.0f,0.0f,-1.0f);       
// 蓝色文字
glColor3ub(0,0,0xff);

// 绘制WGL文字
glRasterPos2f(-0.40f, 0.35f);
glPrint("Active WGL Bitmap Text With NeHe - %7.2f", cnt1);

// 红色文字
glColor3ub(0xff,0,0);

glPushMatrix();
glLoadIdentity();
glRotatef(cnt1,0,0,1);
glScalef(1,.8+.3*cos(cnt1/5),1);
glTranslatef(-180,0,0);
//绘制freetype文字
freetype::print(our_font, 320, 200, "Active FreeType Text - %7.2f", cnt1);
glPopMatrix();

cnt1+=0.051f;
cnt2+=0.005f;
return TRUE; // 成功返回
}

原文及其个版本源代码下载:

http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=43


///

///

经过一个晚上的阅读代码(我的代码阅读能力是很差的).终于知道了如何使用FreeType2了。不过是简单的使用,还不知道如何设置Bold Itainly等属性.主要是简单的演示.以后准备做成一个完善的字体引擎.
下面简单的介绍一下.

首先当然是包含头文件了。头文件要这样包含:
#include [ft2build.h]
#include FT_FREETYPE_H
不知道为什么.反正就是要这么包含.
以下为FT2的初始化代码.和绘制以及释放的代码>
注意这里绘制代码接受的字符是Unicode.表示你这样就可以绘制了

//主要参考了Nehe的Lesson 43(这课的源码可以自己去下载,不过切分字符串那部分有问题,自己重新写个就OK了),经过本人修改后可以正常运算,代码如下:

头文件MyFont.h

//FreeType头文件
#include <ft2build.h>
#include <freetype/freetype.h>
#include <freetype/ftglyph.h>
#include <freetype/ftoutln.h>
#include <freetype/fttrigon.h>

//OpenGL头文件
#include <GL/gl.h>
#include <GL/glu.h>

#include <windows.h>

#pragma comment( lib, "libfreetype.lib")// FT连接库

//STL头文件
#include <vector>
#include <string>

struct WideChar
{
wchar_t data;//宽字符
GLuint texture;//该字符贴图
int left,top,width,height,bmp_width,bmp_rows;//贴图上的文字信息
};

//字体类,使用了FreeType字体引擎,可以读取TTF矢量字体库
class GFont
{
private:
int h; //字体高度
FT_Library library;
FT_Face face;
std::vector<WideChar> WideCharSet;//字符贴图集合

//保证贴图宽高为2的幂(opengl贴图大小限制,3.0除外)
int next_p2 (int a);
//绘制字体形成贴图并保存到vector容器
void CreateWideCharTexture(wchar_t ch,GLuint *texture,int *w,int *h,int *bmp_w,int *bmp_rows,int *left,int *top);
//从容器中获得宽字符的贴图信息
WideChar *GetFontTexture(wchar_t ch);


public:
//FREETYPE初始化
void Init(const char *fname, unsigned int h);
//释放
void Clean();
//绘制文字
void PrintText(const wchar_t *text,float x,float y,float z=0,float r=0,float g=0,float b=0,float a=0);
};

MyFont.cpp文件太大,贴不了,就贴部分重要的,其他的参看Lesson43代码即可

const wchar_t *start_line=text;//换行
vector<wstring> lines;
int length=wcslen(text);
int i=0;
while(i<length)
{
   wstring line;
   while (text[i]!=L'/n'&&text[i]!=L'/0')
   {
    line.append(1,text[i]);
    i++;
   }
   if (!line.empty())
   {
    lines.push_back(line);  
   }
   i++; 
}

int size=lines.size();
for(int row=0;row<size;row++)
{
   glPushMatrix();
   glLoadIdentity();
   glTranslatef(x,y-row*h,0);
   glMultMatrixf(modelview_matrix);
   int len=(lines.at(row)).size();
   WideChar *temp;
   for(int i=0;i<len;i++)
   {
    temp=GetFontTexture((lines.at(row)).at(i));

    glPushMatrix();
    glTranslatef(temp->left,0,0);
    glTranslatef(0,temp->top-temp->bmp_rows,0);

    float x=(float)temp->bmp_width/temp->width,
     y=(float)temp->bmp_rows/temp->height;
   //绘制文字
    glBindTexture(GL_TEXTURE_2D,temp->texture);
    glBegin(GL_QUADS);
    glTexCoord2d(0,0); glVertex2f(0,temp->bmp_rows);
    glTexCoord2d(0,y); glVertex2f(0,0);
    glTexCoord2d(x,y); glVertex2f(temp->bmp_width,0);
    glTexCoord2d(x,0); glVertex2f(temp->bmp_width,temp->bmp_rows);
    glEnd();
    glPopMatrix();
    glTranslatef(face->glyph->advance.x>> 6,0,0); 
   }
   glPopMatrix();
}
glPopAttrib(); 

五六百个中文字符的时候建议优化,以下为本人测试结果:字体库"SIMYOU.TTF",高16

长为724的双字节字符串,未使用优化FPS=6.53,使用算法优化:FPS=8.47,使用算法+显示列表优化:FPS=40.00(均采最高值)

///

//第二篇文章 //

1.FreeType2 是什么?


    它是一个为各种应用程序提供通用的字体文件访问的软件包。尤其值得注意的以下特性:

  • 提供统一的字体文件访问接口。支持位图和向量格式,包括 TrueType 、 OpenType 、 Typel 、 CID 、 CFF 、 Windows FON/FNT 、 X11 PCF 。
  • 提供高效反走样的基于 256 灰度级的位图字形的生产。
  • 模块清晰,每种字体格式对于一个模块。类库的构建可以按照你需要支持的格式进行裁减以减小代码尺寸。(最小的反走样 FreeType 库 <30Kb )


2. FreeType2 能做什么?


    FT2 已经易用于许多领域。例如:

  • 图形子系统和文本显示库
  • 文本排版(布局、分页、渲染)
  • 字体识别和转换工具

    一般来说,该库使得你能轻松的操纵字体文件。


3.如何配置openglfreetype2


4.freetype2 显示汉字


代码:

  1. #include <Windows.h>  
  2. #include <iostream>  
  3. #include <Gl\GL.h>  
  4. #include <Gl\glut.h>    
  5. #include <ft2build.h>  
  6. #include <freetype/freetype.h>  
  7. #include <freetype/ftglyph.h>  
  8. #include <freetype/ftoutln.h>  
  9. #include <freetype/fttrigon.h>  
  10. //#pragma comment(lib , "lib/glut32.lib")  
  11. //#pragma comment(lib , "lib/freetype2110.lib")  
  12. using namespace std;  
  13.   
  14. #define MAX_NO_TEXTURES 1  
  15.   
  16. #define CUBE_TEXTURE 0  
  17.   
  18. GLuint texture_id[MAX_NO_TEXTURES];  
  19.   
  20. struct xCharTexture  
  21. {  
  22.     GLuint  m_texID;  
  23.     wchar_t m_chaID;  
  24.     int     m_Width;  
  25.     int     m_Height;  
  26.   
  27.     int     m_adv_x;  
  28.     int     m_adv_y;  
  29.     int     m_delta_x;  
  30.     int     m_delta_y;  
  31. public:  
  32.     xCharTexture()  
  33.     {  
  34.         m_texID  = 0;  
  35.         m_chaID  = 0;  
  36.         m_Width  = 0;  
  37.         m_Height = 0;  
  38.     }  
  39. }g_TexID[65536];  
  40.   
  41.   
  42. class xFreeTypeLib  
  43. {  
  44.     FT_Library m_FT2Lib;  
  45.     FT_Face    m_FT_Face;  
  46.   
  47. public:  
  48.     int   m_w;  
  49.     int   m_h;  
  50.     void load(const char* font_file , int _w , int _h);  
  51.     GLuint loadChar(wchar_t ch);  
  52. };  
  53.   
  54. void xFreeTypeLib::load(const char* font_file , int _w , int _h)  
  55. {  
  56.     FT_Library library;  
  57.     if (FT_Init_FreeType( &library) )   
  58.         exit(0);  
  59.     //加载一个字体,取默认的Face,一般为Regualer  
  60.     if (FT_New_Face( library, font_file, 0, &m_FT_Face ))   
  61.         exit(0);  
  62.     //选择字符表  
  63.     FT_Select_Charmap(m_FT_Face, FT_ENCODING_UNICODE);  
  64.     m_w = _w ; m_h = _h;  
  65.     m_FT_Face->num_fixed_sizes;  
  66.     //大小要乘64.这是规定。照做就可以了。  
  67.     //FT_Set_Char_Size( m_FT_Face , 0 , m_w << 6, 96, 96);  
  68.     //用来存放指定字符宽度和高度的特定数据  
  69.     FT_Set_Pixel_Sizes(m_FT_Face,m_w, m_h);  
  70. }  
  71.   
  72. GLuint xFreeTypeLib::loadChar(wchar_t ch)  
  73. {  
  74.     if(g_TexID[ch].m_texID)  
  75.     return g_TexID[ch].m_texID;  
  76.     /* 装载字形图像到字形槽(将会抹掉先前的字形图像) */   
  77.     if(FT_Load_Char(m_FT_Face, ch, /*FT_LOAD_RENDER|*/FT_LOAD_FORCE_AUTOHINT|  
  78.         (TRUE ? FT_LOAD_TARGET_NORMAL : FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO) )   )  
  79.     {  
  80.         return 0;  
  81.     }  
  82.   
  83.  /*if(FT_Load_Glyph( m_FT_Face, FT_Get_Char_Index( m_FT_Face, ch ), FT_LOAD_FORCE_AUTOHINT )) 
  84.   throw std::runtime_error("FT_Load_Glyph failed");*/  
  85.   
  86.     xCharTexture& charTex = g_TexID[ch];  
  87.    
  88.     //得到字模  
  89.     FT_Glyph glyph;  
  90.     //把字形图像从字形槽复制到新的FT_Glyph对象glyph中。这个函数返回一个错误码并且设置glyph。   
  91.     if(FT_Get_Glyph( m_FT_Face->glyph, &glyph ))  
  92.         return 0;  
  93.   
  94.     //转化成位图  
  95.     FT_Render_Glyph( m_FT_Face->glyph,   FT_RENDER_MODE_LCD );//FT_RENDER_MODE_NORMAL  );   
  96.     FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1 );  
  97.     FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;  
  98.   
  99.     //取道位图数据  
  100.     FT_Bitmap& bitmap=bitmap_glyph->bitmap;  
  101.   
  102.     //把位图数据拷贝自己定义的数据区里.这样旧可以画到需要的东西上面了。  
  103.     int width  =  bitmap.width;  
  104.     int height =  bitmap.rows;  
  105.    
  106.     m_FT_Face->size->metrics.y_ppem;      //伸缩距离到设备空间  
  107.     m_FT_Face->glyph->metrics.horiAdvance;  //水平文本排列  
  108.   
  109.   
  110.     charTex.m_Width = width;  
  111.     charTex.m_Height = height;  
  112.     charTex.m_adv_x = m_FT_Face->glyph->advance.x / 64.0f;  //步进宽度  
  113.     charTex.m_adv_y = m_FT_Face->size->metrics.y_ppem;        //m_FT_Face->glyph->metrics.horiBearingY / 64.0f;  
  114.     charTex.m_delta_x = (float)bitmap_glyph->left;           //left:字形原点(0,0)到字形位图最左边象素的水平距离.它以整数象素的形式表示。   
  115.     charTex.m_delta_y = (float)bitmap_glyph->top - height;   //Top: 类似于字形槽的bitmap_top字段。  
  116.     glGenTextures(1,&charTex.m_texID);  
  117.     glBindTexture(GL_TEXTURE_2D,charTex.m_texID);  
  118.     char* pBuf = new char[width * height * 4];  
  119.     for(int j=0; j  < height ; j++)  
  120.     {  
  121.         for(int i=0; i < width; i++)  
  122.         {  
  123.             unsigned char _vl =  (i>=bitmap.width || j>=bitmap.rows) ? 0 : bitmap.buffer[i + bitmap.width*j];  
  124.             pBuf[(4*i + (height - j - 1) * width * 4)  ] = 0xFF;  
  125.             pBuf[(4*i + (height - j - 1) * width * 4)+1] = 0xFF;  
  126.             pBuf[(4*i + (height - j - 1) * width * 4)+2] = 0xFF;  
  127.             pBuf[(4*i + (height - j - 1) * width * 4)+3] = _vl;  
  128.         }  
  129.      }  
  130.   
  131.     glTexImage2D( GL_TEXTURE_2D,0,GL_RGBA,width, height,0,GL_RGBA,GL_UNSIGNED_BYTE,pBuf);  //指定一个二维的纹理图片  
  132.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP);                            //glTexParameteri():纹理过滤  
  133.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP);  
  134.     glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );  
  135.     glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );  
  136.     glTexEnvi(GL_TEXTURE_2D,GL_TEXTURE_ENV_MODE,GL_REPLACE);                                //纹理进行混合  
  137.   
  138.     /*gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pBuf); 
  139.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP); 
  140.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP); 
  141.     glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); 
  142.     glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); 
  143.     glTexEnvi(GL_TEXTURE_2D,GL_TEXTURE_ENV_MODE,GL_REPLACE);*/  
  144.     delete[] pBuf;  
  145.     return charTex.m_chaID;  
  146. }  
  147.   
  148.   
  149. xFreeTypeLib g_FreeTypeLib;  
  150. float ratio;  
  151.   
  152. xCharTexture* getTextChar(wchar_t ch)  
  153. {  
  154.     g_FreeTypeLib.loadChar(ch);  
  155.     return &g_TexID[ch];  
  156. }  
  157.   
  158. LPWSTR AnsiToUnicode(LPCSTR lpcstr)   //参数lpcstr类型也可是char*  
  159. {   
  160.     LPWSTR Pwstr;  
  161.     int  i;  
  162.     i=MultiByteToWideChar(CP_ACP,0,lpcstr,-1,NULL,0);  
  163.     Pwstr=new WCHAR[i];   
  164.     MultiByteToWideChar(CP_ACP,0,lpcstr,-1,Pwstr,i);  
  165.   
  166.     return (Pwstr);  
  167. }  
  168.   
  169. //wchar_t g_UnicodeString[]=L"aaabb/x4E2D/x6587/x0031/x0032/x0033";    
  170. const char g_UnicodeString[]="aaa VB文件格式:/n/若不明确就标为未知/n/表演者:";  
  171.   
  172.           
  173. void drawText(wchar_t* _strText,int x , int y, int maxW , int h)  
  174. {  
  175.     int sx = x;  
  176.     int sy = y;  
  177.     int maxH = h;  
  178.     size_t nLen = wcslen(_strText);  
  179.   
  180.     for(int i = 0 ; i <nLen ; i ++)  
  181.     {  
  182.         if(_strText[i] =='/n')  
  183.         {  
  184.             sx = x ; sy += maxH + 12;  
  185.             continue;  
  186.         }  
  187.         xCharTexture* pCharTex = getTextChar(_strText[i]);  
  188.         glBindTexture(GL_TEXTURE_2D,pCharTex->m_texID);                          //绑定到目标纹理  
  189.         glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );     
  190.         glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );  
  191.         glEnable(GL_BLEND);                                                     //打开或关闭OpenGL的特殊功能  
  192.         glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);                       //特殊的像素算法  
  193.         //glDisable(GL_TEXTURE_2D);  
  194.         int w = pCharTex->m_Width;  
  195.         int h = pCharTex->m_Height;  
  196.   
  197.         int ch_x = sx + pCharTex->m_delta_x;  
  198.         int ch_y = sy - h - pCharTex->m_delta_y;  
  199.   
  200.         if(maxH < h) maxH = h;  
  201.         glBegin ( GL_QUADS );                                                    // 定义一个或一组原始的顶点  
  202.         {  
  203.             glTexCoord2f(0.0f, 1.0f); glVertex3f(ch_x      , ch_y    ,  1.0f);  
  204.             glTexCoord2f(1.0f, 1.0f); glVertex3f(ch_x +  w, ch_y    ,  1.0f);  
  205.             glTexCoord2f(1.0f, 0.0f); glVertex3f(ch_x +  w, ch_y + h,  1.0f);  
  206.             glTexCoord2f(0.0f, 0.0f); glVertex3f(ch_x     , ch_y + h,  1.0f);  
  207.         }  
  208.         glEnd();  
  209.         sx += pCharTex->m_adv_x;  
  210.         if(sx > x + maxW)  
  211.         {  
  212.             sx = x ; sy += maxH + 12;  
  213.         }  
  214.     }  
  215. }  
  216.   
  217. void init(void)  
  218. {  
  219.     glShadeModel(GL_SMOOTH|GL_FLAT);                        //选择平直或平滑着色  
  220.     glClearColor(0.0f, 0.0f, 0.0f, 0.5f);                   //清除色彩缓冲区  
  221.     glEnable ( GL_COLOR_MATERIAL_FACE );  
  222.     glColorMaterial ( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );   // 使一个材质色彩指向当前的色彩  
  223.   
  224.     //g_FreeTypeLib.load("simhei.ttf",14,14);  
  225.     // g_FreeTypeLib.load("c://windows//fonts//simhei.ttf",14,14);  
  226.     g_FreeTypeLib.load("c://windows//fonts//simhei.ttf",12,12);  
  227.   
  228.     glDisable ( GL_CULL_FACE );  
  229.   
  230.     //glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  
  231. }  
  232.   
  233. void reshape( int w, int h )  
  234. {  
  235.  // Prevent a divide by zero, when window is too short  
  236.  // (you cant make a window of zero width).  
  237.  if(h == 0)  
  238.   h = 1;  
  239.   
  240.  ratio = 1.0f * w / h;  
  241.  // Reset the coordinate system before modifying  
  242.  glMatrixMode(GL_PROJECTION);                           //定义矩阵  
  243.  glLoadIdentity();                                      //用恒等矩阵替换当前矩阵  
  244.    
  245.  // Set the viewport to be the entire window  
  246.     glViewport(0, 0, w, h);                             //设置视窗  
  247.     glOrtho(0,w,h,0,-100,200);                          //用垂直矩阵与当前矩阵相乘  
  248.  // Set the clipping volume  
  249.  glMatrixMode(GL_MODELVIEW);  
  250.  glLoadIdentity();                    
  251.  gluLookAt(0, 0, 30 ,0 , 0 ,10 , 0.0f , 1.0f , 0.0f);   //设定一个变换视点  
  252. }  
  253.   
  254. void display( void )  
  255. {  
  256.    glClearColor(0.0f , 0.0f , 0.6f , 1.0f);  
  257.    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );  
  258.    /*glLoadIdentity ( ); 
  259.    glPushMatrix(); 
  260.    glTranslatef ( 0.0, 0.0, -5.0 ); 
  261.    */  
  262.    glEnable ( GL_TEXTURE_2D );  
  263.    wchar_t *wstr = AnsiToUnicode(g_UnicodeString);  
  264.    drawText(wstr, 50, 50, 900,25);  
  265.    //glPopMatrix();  
  266.    glutSwapBuffers();  
  267. }  
  268.   
  269. void keyboard ( unsigned char key, int x, int y )  // Create Keyboard Function  
  270. {  
  271.   switch ( key ) {  
  272.     case 27:        // When Escape Is Pressed...  
  273.       exit ( 0 );   // Exit The Program  
  274.       break;        // Ready For Next Case  
  275.     default:        // Now Wrap It Up  
  276.       break;  
  277.   }  
  278. }  
  279.   
  280. void arrow_keys ( int a_keys, int x, int y )   // Create Special Function (required for arrow keys)  
  281. {  
  282.   switch ( a_keys ) {  
  283.     case GLUT_KEY_UP:     // When Up Arrow Is Pressed...  
  284.       glutFullScreen ( ); // Go Into Full Screen Mode  
  285.       break;  
  286.     case GLUT_KEY_DOWN:                 // When Down Arrow Is Pressed...  
  287.       glutReshapeWindow ( 900, 500 );   // Go Into A 500 By 500 Window  
  288.       break;  
  289.     default:  
  290.       break;  
  291.   }  
  292. }  
  293.   
  294.   
  295. void myDisplay(void)    
  296.   
  297. {    
  298.   
  299.     glClear(GL_COLOR_BUFFER_BIT);    
  300.   
  301.     glColor3f (1.0,0.0,0.0);    
  302.     glBegin (GL_LINES);    
  303.     glVertex2i (180,15);    
  304.     glVertex2i (10,145);    
  305.     glEnd();    
  306.   
  307.     glRectf(-0.5f, -0.5f, 0.5f, 0.5f);    
  308.   
  309.     glFlush();    
  310.   
  311. }    
  312.   
  313. int main(int argc,char * argv[])    
  314. {    
  315.   
  316.     //ANSI字符串,内容长度7字节     
  317.     char sz[20] = "中文123";    
  318.   
  319.     //UNICODE字符串,内容长度5个wchar_t(10字节)     
  320.     wchar_t   wsz[100]   =   L"/x4E2D/x6587/x0031/x0032/x0033";        
  321.     //运行时设定当前ANSI编码,VC格式     
  322.     setlocale(LC_ALL,".936");    
  323.   
  324.     //GCC中格式     
  325.     setlocale(LC_ALL, "zh_CN.GBK");    
  326.   
  327.     //VisualC++中使用小写%s,按照setlocale指定编码输出到文件     
  328.     //GCC中使用大写%S     
  329.   
  330.   
  331.     //把UNICODE字符串按照setlocale指定的编码转换成字节     
  332.     wcstombs(sz,   wsz,   20);     
  333.     //把字节串按照setlocale指定的编码转换成UNICODE字符串     
  334.     mbstowcs(wsz,   sz,   20);      
  335.   
  336.     glutInit( &argc, argv );                                       //用于初始化GULT库  
  337.     glutInitDisplayMode ( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA );  //设置初始显示模式  
  338.     glutInitWindowPosition (0,0);                                  //确定窗口的位置  
  339.     glutInitWindowSize  ( 900, 500 );                              //设置窗口大小  
  340.     glutCreateWindow    ( "NeHe Lesson 6- Ported by Rustad" );     //创建一个窗口标题  
  341.     init ();  
  342.     //glutFullScreen      ( );          //Put Into Full Screen  
  343.     glutDisplayFunc     ( display );    //注册一个绘图函数  
  344.     glutReshapeFunc     ( reshape );    //设置投影的函数  
  345.     glutKeyboardFunc    ( keyboard );   //键盘回调函数  
  346.     glutSpecialFunc     ( arrow_keys ); //设置当前窗口的特殊键盘回调。  
  347.     glutIdleFunc    ( display );        //程序空闲时调用的函数  
  348.     glutMainLoop        ( );            // 进入GLUT事件处理循环  
  349.   
  350.     return 0;    
  351.   
  352. }    

运行效果图:




freetype2学习资源:

[精华] FreeType 2开发文档 [中译版]:http://www.unixresources.NET/Linux/clf/kylix/archive/00/00/59/21/592188.html


FreeType 2官方网:http://www.freetype.org/freetype2/





  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值