【OpenGL游戏开发之五】freetype2 显示汉字

来源:互联网 发布:云杉网络 张天鹏 编辑:程序博客网 时间:2024/06/17 22:09

1.FreeType2 是什么?


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

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


2. FreeType2 能做什么?


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

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

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


3.如何配置opengl,freetype2


4.freetype2 显示汉字


代码:

#include <Windows.h>#include <iostream>#include <Gl\GL.h>#include <Gl\glut.h>  #include <ft2build.h>#include <freetype/freetype.h>#include <freetype/ftglyph.h>#include <freetype/ftoutln.h>#include <freetype/fttrigon.h>//#pragma comment(lib , "lib/glut32.lib")//#pragma comment(lib , "lib/freetype2110.lib")using namespace std;#define MAX_NO_TEXTURES 1#define CUBE_TEXTURE 0GLuint texture_id[MAX_NO_TEXTURES];struct xCharTexture{GLuint  m_texID;wchar_t m_chaID;int     m_Width;int     m_Height;int     m_adv_x;int     m_adv_y;int     m_delta_x;int     m_delta_y;public:xCharTexture(){m_texID  = 0;m_chaID  = 0;m_Width  = 0;m_Height = 0;}}g_TexID[65536];class xFreeTypeLib{FT_Library m_FT2Lib;FT_Face    m_FT_Face;public:int   m_w;int   m_h;void load(const char* font_file , int _w , int _h);GLuint loadChar(wchar_t ch);};void xFreeTypeLib::load(const char* font_file , int _w , int _h){FT_Library library;if (FT_Init_FreeType( &library) ) exit(0);//加载一个字体,取默认的Face,一般为Regualerif (FT_New_Face( library, font_file, 0, &m_FT_Face )) exit(0);//选择字符表FT_Select_Charmap(m_FT_Face, FT_ENCODING_UNICODE);m_w = _w ; m_h = _h;m_FT_Face->num_fixed_sizes;//大小要乘64.这是规定。照做就可以了。//FT_Set_Char_Size( m_FT_Face , 0 , m_w << 6, 96, 96);//用来存放指定字符宽度和高度的特定数据FT_Set_Pixel_Sizes(m_FT_Face,m_w, m_h);}GLuint xFreeTypeLib::loadChar(wchar_t ch){if(g_TexID[ch].m_texID)return g_TexID[ch].m_texID;/* 装载字形图像到字形槽(将会抹掉先前的字形图像) */ if(FT_Load_Char(m_FT_Face, ch, /*FT_LOAD_RENDER|*/FT_LOAD_FORCE_AUTOHINT|(TRUE ? FT_LOAD_TARGET_NORMAL : FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO) )   ){return 0;} /*if(FT_Load_Glyph( m_FT_Face, FT_Get_Char_Index( m_FT_Face, ch ), FT_LOAD_FORCE_AUTOHINT ))  throw std::runtime_error("FT_Load_Glyph failed");*/xCharTexture& charTex = g_TexID[ch]; //得到字模FT_Glyph glyph;//把字形图像从字形槽复制到新的FT_Glyph对象glyph中。这个函数返回一个错误码并且设置glyph。 if(FT_Get_Glyph( m_FT_Face->glyph, &glyph ))return 0; //转化成位图 FT_Render_Glyph( m_FT_Face->glyph,   FT_RENDER_MODE_LCD );//FT_RENDER_MODE_NORMAL  );  FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1 ); FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;//取道位图数据FT_Bitmap& bitmap=bitmap_glyph->bitmap;//把位图数据拷贝自己定义的数据区里.这样旧可以画到需要的东西上面了。int width  =  bitmap.width;int height =  bitmap.rows; m_FT_Face->size->metrics.y_ppem;//伸缩距离到设备空间m_FT_Face->glyph->metrics.horiAdvance;  //水平文本排列charTex.m_Width = width;charTex.m_Height = height;charTex.m_adv_x = m_FT_Face->glyph->advance.x / 64.0f;  //步进宽度charTex.m_adv_y = m_FT_Face->size->metrics.y_ppem;//m_FT_Face->glyph->metrics.horiBearingY / 64.0f;charTex.m_delta_x = (float)bitmap_glyph->left;//left:字形原点(0,0)到字形位图最左边象素的水平距离.它以整数象素的形式表示。 charTex.m_delta_y = (float)bitmap_glyph->top - height;//Top: 类似于字形槽的bitmap_top字段。glGenTextures(1,&charTex.m_texID);glBindTexture(GL_TEXTURE_2D,charTex.m_texID);char* pBuf = new char[width * height * 4];for(int j=0; j  < height ; j++){for(int i=0; i < width; i++){   unsigned char _vl =  (i>=bitmap.width || j>=bitmap.rows) ? 0 : bitmap.buffer[i + bitmap.width*j];  pBuf[(4*i + (height - j - 1) * width * 4)  ] = 0xFF;   pBuf[(4*i + (height - j - 1) * width * 4)+1] = 0xFF;   pBuf[(4*i + (height - j - 1) * width * 4)+2] = 0xFF;   pBuf[(4*i + (height - j - 1) * width * 4)+3] = _vl;  } }glTexImage2D( GL_TEXTURE_2D,0,GL_RGBA,width, height,0,GL_RGBA,GL_UNSIGNED_BYTE,pBuf);  //指定一个二维的纹理图片glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP);   //glTexParameteri():纹理过滤glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP);glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );glTexEnvi(GL_TEXTURE_2D,GL_TEXTURE_ENV_MODE,GL_REPLACE);//纹理进行混合/*gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pBuf);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP);glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );glTexEnvi(GL_TEXTURE_2D,GL_TEXTURE_ENV_MODE,GL_REPLACE);*/delete[] pBuf;return charTex.m_chaID;}xFreeTypeLib g_FreeTypeLib;float ratio;xCharTexture* getTextChar(wchar_t ch){g_FreeTypeLib.loadChar(ch);return &g_TexID[ch];}LPWSTR AnsiToUnicode(LPCSTR lpcstr)   //参数lpcstr类型也可是char*{ LPWSTR Pwstr;int  i;i=MultiByteToWideChar(CP_ACP,0,lpcstr,-1,NULL,0);Pwstr=new WCHAR[i]; MultiByteToWideChar(CP_ACP,0,lpcstr,-1,Pwstr,i);return (Pwstr);}//wchar_t g_UnicodeString[]=L"aaabb/x4E2D/x6587/x0031/x0032/x0033";  const char g_UnicodeString[]="aaa VB文件格式:/n/若不明确就标为未知/n/表演者:";void drawText(wchar_t* _strText,int x , int y, int maxW , int h){int sx = x;int sy = y;int maxH = h;size_t nLen = wcslen(_strText);for(int i = 0 ; i <nLen ; i ++){if(_strText[i] =='/n'){sx = x ; sy += maxH + 12;continue;}xCharTexture* pCharTex = getTextChar(_strText[i]);glBindTexture(GL_TEXTURE_2D,pCharTex->m_texID);//绑定到目标纹理glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );glEnable(GL_BLEND);//打开或关闭OpenGL的特殊功能glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);//特殊的像素算法//glDisable(GL_TEXTURE_2D);int w = pCharTex->m_Width;int h = pCharTex->m_Height;int ch_x = sx + pCharTex->m_delta_x;int ch_y = sy - h - pCharTex->m_delta_y;if(maxH < h) maxH = h;glBegin ( GL_QUADS ); // 定义一个或一组原始的顶点{glTexCoord2f(0.0f, 1.0f); glVertex3f(ch_x      , ch_y    ,  1.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(ch_x +  w, ch_y    ,  1.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(ch_x +  w, ch_y + h,  1.0f);glTexCoord2f(0.0f, 0.0f); glVertex3f(ch_x     , ch_y + h,  1.0f);}glEnd();sx += pCharTex->m_adv_x;if(sx > x + maxW){sx = x ; sy += maxH + 12;}}}void init(void){glShadeModel(GL_SMOOTH|GL_FLAT);//选择平直或平滑着色glClearColor(0.0f, 0.0f, 0.0f, 0.5f);//清除色彩缓冲区glEnable ( GL_COLOR_MATERIAL_FACE );glColorMaterial ( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );// 使一个材质色彩指向当前的色彩//g_FreeTypeLib.load("simhei.ttf",14,14);// g_FreeTypeLib.load("c://windows//fonts//simhei.ttf",14,14);g_FreeTypeLib.load("c://windows//fonts//simhei.ttf",12,12);glDisable ( GL_CULL_FACE );//glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);}void reshape( int w, int h ){ // Prevent a divide by zero, when window is too short // (you cant make a window of zero width). if(h == 0)  h = 1; ratio = 1.0f * w / h; // Reset the coordinate system before modifying glMatrixMode(GL_PROJECTION);//定义矩阵 glLoadIdentity();//用恒等矩阵替换当前矩阵  // Set the viewport to be the entire window    glViewport(0, 0, w, h);//设置视窗    glOrtho(0,w,h,0,-100,200);//用垂直矩阵与当前矩阵相乘 // Set the clipping volume glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0, 0, 30 ,0 , 0 ,10 , 0.0f , 1.0f , 0.0f);//设定一个变换视点}void display( void ){   glClearColor(0.0f , 0.0f , 0.6f , 1.0f);   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );   /*glLoadIdentity ( );   glPushMatrix();   glTranslatef ( 0.0, 0.0, -5.0 );   */   glEnable ( GL_TEXTURE_2D );   wchar_t *wstr = AnsiToUnicode(g_UnicodeString);   drawText(wstr, 50, 50, 900,25);   //glPopMatrix();   glutSwapBuffers();}void keyboard ( unsigned char key, int x, int y )  // Create Keyboard Function{  switch ( key ) {    case 27:        // When Escape Is Pressed...      exit ( 0 );   // Exit The Program      break;        // Ready For Next Case    default:        // Now Wrap It Up      break;  }}void arrow_keys ( int a_keys, int x, int y )   // Create Special Function (required for arrow keys){  switch ( a_keys ) {    case GLUT_KEY_UP:     // When Up Arrow Is Pressed...      glutFullScreen ( ); // Go Into Full Screen Mode      break;    case GLUT_KEY_DOWN:                 // When Down Arrow Is Pressed...      glutReshapeWindow ( 900, 500 );   // Go Into A 500 By 500 Window      break;    default:      break;  }}void myDisplay(void)  {  glClear(GL_COLOR_BUFFER_BIT);  glColor3f (1.0,0.0,0.0);  glBegin (GL_LINES);  glVertex2i (180,15);  glVertex2i (10,145);  glEnd();  glRectf(-0.5f, -0.5f, 0.5f, 0.5f);  glFlush();  }  int main(int argc,char * argv[])  {  //ANSI字符串,内容长度7字节   char sz[20] = "中文123";  //UNICODE字符串,内容长度5个wchar_t(10字节)   wchar_t   wsz[100]   =   L"/x4E2D/x6587/x0031/x0032/x0033";      //运行时设定当前ANSI编码,VC格式   setlocale(LC_ALL,".936");  //GCC中格式   setlocale(LC_ALL, "zh_CN.GBK");  //VisualC++中使用小写%s,按照setlocale指定编码输出到文件   //GCC中使用大写%S   //把UNICODE字符串按照setlocale指定的编码转换成字节   wcstombs(sz,   wsz,   20);   //把字节串按照setlocale指定的编码转换成UNICODE字符串   mbstowcs(wsz,   sz,   20);    glutInit( &argc, argv );   //用于初始化GULT库glutInitDisplayMode ( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA );  //设置初始显示模式glutInitWindowPosition (0,0);   //确定窗口的位置glutInitWindowSize  ( 900, 500 );   //设置窗口大小glutCreateWindow    ( "NeHe Lesson 6- Ported by Rustad" );   //创建一个窗口标题init ();//glutFullScreen      ( );          //Put Into Full ScreenglutDisplayFunc     ( display );//注册一个绘图函数glutReshapeFunc     ( reshape );//设置投影的函数glutKeyboardFunc    ( keyboard );//键盘回调函数glutSpecialFunc     ( arrow_keys );//设置当前窗口的特殊键盘回调。glutIdleFunc    ( display );//程序空闲时调用的函数glutMainLoop        ( );// 进入GLUT事件处理循环return 0;  }  

运行效果图:




freetype2学习资源:

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

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


0 0
原创粉丝点击