OpenGL系统设计-位图 字体(3) 汉字显示

 汉字显示

对于汉字的字符作为位图显示时,如果采用上面的办法就会很麻烦,你必须把一个16X16点阵汉字的32个字节的点阵数据描述出来,如果有多个汉字或者汉字的点阵数目更多,如36X36等,工作量就会增加很多,并且手工处理点阵数据又容易出错。

因此,为了解决汉字点阵字符问题,我们可以借助于点阵汉字库来解决这个问题。通常汉字的存储是以机器内码的方式进行的,每个汉字占用两个字节,这两个字节都大于128,更严格来说,汉字的两个字节大小范围介于0xA10xFE之间。

汉字点阵字库通常是根据区位码来存储的,如果知道区位码,就可以得到汉字的点阵数据在字库文件中的偏移量,从而得到点阵数据。如果汉字的区码为qm,位码为wm,则16x16汉字点阵数据的偏移量offset就是

 

offset = ((qm-1)*94+(wm-1))*32;

 

因为每一个区的汉字数为94个,每一个汉字的点阵数据为32个字节。对于不同的字库,可能偏移量不完全相同,但是也是具有一个固定的差值,尝试一下就知道是多少了。

而区位码和汉字机器内码又有固定的关系,因此,通过一个汉字就可以得到其点阵数据。如果汉字机器内码的两个字节分别是nm0(高位), nm1(低位),则其区码和位码分别是

 

qm = (nm0 & 0x7F)-32;

wm = (nm1 & 0x7F)-32;

 

知道了如何获取汉字点阵数据的原理,下面就是通过代码来实现了。

 

BOOL LoadHZLib(char *);

 

char *hzBuffer, *pBuffer;

void glTextHZChar(char *str,  int x, int y, int length);

 

GLubyte hzBitmap[256][32]; //这里最多支持256个汉字的字符串,如果需要更多,

//把数组改大即可

 

 

BOOL LoadHZLib(char *filename)

{

   int hzHandle;

   int length;

 

   //打开点阵字库文件

   hzHandle = _open(filename, _O_RDWR);

   if(hzHandle <0)

   {

       MessageBox(NULL, "Can't open HZ lib!", "ERROR", MB_OK);

       return FALSE;

   }

 

  

   //取得字库文件的长度

   length = _filelength(hzHandle);

   if(length <0)

   {

       _close(hzHandle);

       MessageBox(NULL, "The length of lib file is error!", "ERROR", MB_OK);

       return FALSE;

 

   }

 

   //根据字库文件的大小分配内存,以便把整个字库文件都装入到内存中

   hzBuffer = (char *)malloc(length);

   if(!hzBuffer)

   {

       _close(hzHandle);

       MessageBox(NULL, "Malloc error!", "ERROR", MB_OK);

       return FALSE;

   }

 

   if (_read(hzHandle, hzBuffer, length) <= 0)

   {

       _close(hzHandle);

       free(hzBuffer);

       hzBuffer = NULL;

       MessageBox(NULL, "Read error!", "ERROR", MB_OK);

       return FALSE;

   }

 

   _close(hzHandle);

  

   return TRUE;   

 

}

 

glInit()中只需要加载汉字库

 

int glInit()

{

 

   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

   glClearColor(1.0f,1.0f,1.0f,0.0f);

 

   if(!LoadHZLib("hzk16"))

   {

       return FALSE;

   }

 

   return TRUE;

}

 

glTextHZChar是一个自定义函数,用于将一串汉字文本显示在屏幕(x, y)处,length是字符串的长度。

 

void  glTextHZChar(char *str, int x, int y,  int length)

{

   int i,j;

   int qm, wm;

 

   GLubyte temp;

 

   //限制字符串的长度

   if(length>256)

   {

       return;

   }

  

   //将当前的变换属性值视点属性值压入属性堆栈

   glPushAttrib( GL_TRANSFORM_BIT | GL_VIEWPORT_BIT );

 

   // 使用新的投影矩阵和模型观察矩阵

   glMatrixMode( GL_PROJECTION );  // 设置我们的投影矩阵

   glPushMatrix();                    

   glLoadIdentity();                   // 使用新的投影矩阵

   glMatrixMode( GL_MODELVIEW );   // 设置观察矩阵

   glPushMatrix();                    

   glLoadIdentity();                   // 使用新的观察矩阵

 

   glViewport( x, y, 0, 0 );               // 创建一个新的视点

 

   glRasterPos4f( 0.0, 0.0, 0.0, 1.0 );    // 设置绘图位置(x, y, z, w)

 

   for(j=0; j<length; j++)

   {

 

       //计算汉字的区位码

       qm=(str[2*j] & 0x7F)-32;    //区码=(头一字节内码 &0x7F)-32

       wm=(str[2*j+1] & 0x7F)-32;  //位码=(第二字节内码 &0x7F)-32

      

       pBuffer=hzBuffer + ((qm-1)*94+(wm-1))*32;

 

       memcpy(hzBitmap[j], pBuffer, 32);

 

       //因为显示图像时,是从下到上显示的,而点阵数据是按照从上到下保存的

       //这里对读取的数据进行上下对调

       for(i=0; i<16; i++)

       {

           temp = hzBitmap[j][i];

           hzBitmap[j][i] = hzBitmap[j][31-i];

           hzBitmap[j][31-i] = temp;

 

       }

 

       for(i=0; i<16; i++)

       {

           temp = hzBitmap[j][2*i];

           hzBitmap[j][2*i] = hzBitmap[j][2*i+1];

           hzBitmap[j][2*i+1] = temp;

       }

  

       glBitmap(16, 16, 0, 0, 16, 0, hzBitmap[j]);

   }

 

   //恢复模型观察矩阵

   glPopMatrix();             

 

   //恢复投影矩阵

   glMatrixMode( GL_PROJECTION );         

   glPopMatrix();                         

 

   //恢复变换和视点的属性值

   glPopAttrib();     

  

}

 

 

void glMain()

{

  

   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

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

 

 

   glColor3f(0.0f, 0.0f, 0.0f);

   glTextHZChar("欢迎来到OpenGL世界", 10, 150, 12);

 

   glColor3f(1.0, 0.0, 1.0);

   glTextHZChar("我喜欢OpenGL", 10, 100, 9);

 

   glColor3f(0.0, 1.0, 1.0);

   glTextHZChar("在OpenGL中汉字的点阵位图显示", 10, 60, 17);

 

 

   SwapBuffers(g_hDC);

} 

 

 

最后不要忘了释放掉hzBuffer所占用的内存。

 

void glShutdown()

{

   ……

 

   if(hzBuffer)

   {

       free(hzBuffer);

       hzBuffer=NULL;

   }

 

}

 

 

程序运行后,可以看到三行不同颜色的汉字文本显示在窗口内,效果如图8-5所示。这里的字体是标准的16X16点阵的宋体,如果想显示其他大小和类型的字体,如繁体、隶书等,需要有相应的点阵字库,并且对glHZChar()进行一定的修改。

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值