网页功能: 加入收藏 设为首页 网站搜索  
OpenGL实现中文显示
发表日期:2007-03-28作者:[转贴] 出处:  
 


OpenGL实现中文显示


      用OpenGL显示文字,一般使用wglUseFontOutLines以及wglUseFontBitMaps函数(Windows平台)。如果显示单字节文字(英文,法文,拉丁文……),效果很好;如果显示双字节文字(中文,日文,韩文……),效果就不太好了。
      用wglUseFontOutLines时,文字较小会看不清笔画(用Windows的屏保“三维文字”就能发现);而wglUseFontBitMaps无法显示中文。那么贴图文字呢? 如果用字量不大,还是不要麻烦她了。
      经过一番研究,我写了一个类可以实现中文的位图显示。源代码如下:

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Graphics, GL, GLu, GLext;

Type
  PGLFont = ^TGLFont;
  TGLFont = record
    b3D     : Boolean;
    bBold   : Boolean;
    bItalic : Boolean;
    Height  : Integer;
    Weight  : Integer;
    CharSet : Cardinal;
    Typeface: PChar;
  end;
  TGLText = class
  private
    GLStrEng   : PChar;
    GLStrChn   : PChar;

    procedure Build(srcDC: HDC; glStr: PChar; glFont: PGLFont);
    procedure wglUseFontBitmapsExt(srcDC : HDC; First, Count, ListBase 
: DWORD);
  public
    constructor Create(srcDC : HDC; EngStr, ChnStr : PChar;
                       EngFont, ChnFont : PGLFont);
    destructor Destroy; override;
    procedure glShowStr(glStr : PChar);
  end;


implementation

{ TGLText }
procedure TGLText.Build(srcDC: HDC; glStr: PChar; glFont: PGLFont);
var
  i,
  Chartmp     : Byte;
  Font, oFont : HFONT;
  glBold      : Integer;
  glItalic    : Cardinal;
  dwChar      : DWORD;
  gmf         : GLYPHMETRICSFLOAT;
begin

  if glFont.bBold then
    glBold := FW_BOLD
  else
    glBold := FW_NORMAL;

  if glFont.bItalic then
    glItalic := 1
  else
    glItalic := 0;

  Font := CreateFont(glFont.Height, glFont.Weight, 0, 0, glBold, 
glItalic,
                     0, 0, glFont.CharSet, OUT_TT_PRECIS,
                     CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
                     FF_DONTCARE or DEFAULT_PITCH,
                     glFont.Typeface);

  oFont := SelectObject(srcDC, Font);

  if glStr = 'All English' then
  begin
    for i := 32 to 125 do
      if glFont.b3D then
        wglUseFontOutLines(srcDC, i, 1, i, 0, 0, WGL_FONT_POLYGONS, 
@gmf)
      else
        wglUseFontBitMaps(srcDC, i, 1, i);
  end
  else
  begin
    i := 0;
    While i < StrLen(glStr) do
    begin
      Chartmp := Byte(glStr[i]);
      if IsDBCSLeadByte(Chartmp) then
      begin
        dwChar := ((Chartmp shl 8) or Byte(glStr[i+1]));
        i := i + 2;
      end
      else
      begin
        dwChar := Chartmp;
        i := i + 1;
      end;
      if glFont.b3D then
        wglUseFontOutLines(srcDC, dwChar, 1, dwChar, 0, 0,
                           WGL_FONT_POLYGONS, @gmf)
      else
        wglUseFontBitMapsExt(srcDC, dwChar, 1, dwChar);
    end;
  end;

  SelectObject(srcDC, oFont);
  DeleteObject(Font);

end;

constructor TGLText.Create(srcDC : HDC; EngStr, ChnStr: PChar;
                           EngFont, ChnFont: PGLFont);
begin

  GLStrEng := EngStr;
  GLStrChn := ChnStr;

  if EngStr <> nil then
      Build(srcDC, EngStr, EngFont);

  if ChnStr <> nil then
      Build(srcDC, ChnStr, ChnFont);

end;

destructor TGLText.Destroy;
var
  i,
  Chartmp : Byte;
  dwChar  : DWORD;
begin

  if GLStrEng <> nil then
    if GLStrEng = 'All English' then
    begin
      glDeleteLists(32, 93);
    end
    else
    begin
      i := 0;
      While i < StrLen(GLStrEng) do
      begin
        dwChar := Byte(GLStrEng[i]);
        glDeleteLists(dwChar, 1);
        i := i + 1;
      end;
    end;

  if GLStrChn <> nil then
  begin
    i := 0;
    While i < StrLen(GLStrChn) do
    begin
      Chartmp := Byte(GLStrChn[i]);
      if IsDBCSLeadByte(Chartmp) then
      begin
        dwChar := ((Chartmp shl 8) or Byte(GLStrChn[i+1]));
        i := i + 2;
      end
      else
      begin
        dwChar := Chartmp;
        i := i + 1;
      end;
      glDeleteLists(dwChar, 1);
    end;
  end;

  inherited Destroy;

end;

procedure TGLText.glShowStr(glStr : PChar);
var
  i,
  Chartmp     : Byte;
  dwChar      : DWORD;
begin

  i := 0;
  While i < StrLen(glStr) do
  begin
    Chartmp := Byte(glStr[i]);
    if IsDBCSLeadByte(Chartmp) then
    begin
      dwChar := ((Chartmp shl 8) or Byte(glStr[i+1]));
      i := i + 2;
    end
    else
    begin
      dwChar := Chartmp;
      i := i + 1;
    end;
    glCallList(dwChar);
  end;

end;

procedure TGLText.wglUseFontBitmapsExt(srcDC: HDC; First, Count,
                                       ListBase: DWORD);
var
  i : DWORD;
  size : DWORD;
  gm : GLYPHMETRICS;
  hBits : THANDLE;
  lpBits : PGLubyte;
  mat : MAT2;
begin

  mat.eM11.fract := 0;
  mat.eM11.value := 1;
  mat.eM12.fract := 0;
  mat.eM12.value := 0;
  mat.eM21.fract := 0;
  mat.eM21.value := 0;
  mat.eM22.fract := 0;
  mat.eM22.value := -1;

  for i := 0 to Count - 1 do
  begin
     glNewList(ListBase+i, GL_COMPILE);

     size := GetGlyphOutline(srcDC, First+i, GGO_BITMAP, gm, 0, nil, mat);

      hBits  := GlobalAlloc(GHND, size);
      lpBits := GlobalLock(hBits);

      GetGlyphOutline(srcDC,               //* handle to device context */
                                  First+i,              //* character to query */
                                  GGO_BITMAP,  //* format of data to return */
                                  gm,                   //* pointer to structure for metrics */
                                  size,                  //* size of buffer for data */
                                  lpBits,               //* pointer to buffer for data */
                                  mat                   //* pointer to transformation */
                                                           //* matrix structure */
                      );

      glBitmap(gm.gmBlackBoxX,gm.gmBlackBoxY,
               gm.gmptGlyphOrigin.x,
               gm.gmptGlyphOrigin.y,
               gm.gmCellIncX,gm.gmCellIncY,
               lpBits);


      GlobalUnlock(hBits);
      GlobalFree(hBits);

    glEndList;
  end;

end;

end.

我用的是Delphi 6。最终显示还可以,但并不完美。不知有谁可以改进?欢迎交流,我的邮箱testerHooK@126.com
由于网络原因演示程序(含源代码)请发邮件索取。

P.S. 演示程序用到了DOT工具,请到www.delphi3d.net下载最新版。 

我来说两句】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 OpenGL实现中文显示
本类热点文章
  DDraw和D3D立即模式编程手册
  矩阵求逆的快速算法
  本地化支持:OGRE+CEGUI中文输入:OGRE方..
  Direct3D中实现图元的鼠标拾取
  3D场景中的圆形天空顶
  OpenGL显卡编程
  一种高效的基于大规模地形场景的OCCLUS..
  一个完善的读取3DS文件例子
  如何制作一个可控制的人体骨骼模型
  Direct3D 入门之我见
  Slope(斜坡) 法线生成算法,在地形渲染..
  在Direct3D中渲染文字
最新分类信息我要发布 
最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放  
Copyright ©2003-2024 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00557