HGE的中文显示解决方案 .

最近在自己借鉴hge写一个2d游戏引擎,无意中看到中文字体的简单解决方案,先记下来备忘。

HGE本身并不支持中文的显示,因此我使用由 微妙的平衡 大神提供的解决方案.

大神提供的代码本来包含gfxfont.h和gfxfont.cpp文件,只需要将这两个文件添加到工程中即可使用.

但是我实在太懒,为了避免每次都添加两个文件到工程中去,于是我擅自将cpp的代码全部移到了.h文件中并做了一些细微的改动.

这样每次使用的时候就只需要将gfxfont.h引入工程就够了,当然我把这个gfxfont.h直接放到了hge的include文件夹中,这样我就可以直接

用#include 来引用这个文件了.(当然,要先hge的include目录添加到工程中去.)

以下是gfxfont.h文件的源码:

[cpp] view plain copy print ?
  1. gfxfont.h  
  2. #ifndef GDIFONT_H   
  3. #define GDIFONT_H   
  4.   
  5. #include    
  6. #include    
  7. #include    
  8. #pragma comment(linker,"/NODEFAULTLIB:libc.lib")   
  9.   
  10. __inline float _floor(float f)  
  11. {  
  12.     static int _n;  
  13.     _asm fld f  
  14.     _asm fistp _n  
  15.     return (float)_n;  
  16. }  
  17.   
  18. class GfxFont  
  19. {  
  20. public:  
  21.     static const unsigned char g_byAlphaLevel[65];  
  22.     GfxFont(const char* lpsFontName, int nFaceSize, BOOL bBold = FALSE, BOOL bItalic = FALSE, BOOL bAntialias = TRUE)  
  23.     {  
  24.         m_pHGE = hgeCreate(HGE_VERSION);  
  25.   
  26.         // 创建GDI相关设备   
  27.         HDC hDC = GetDC(m_pHGE->System_GetState(HGE_HWND));  
  28.         m_hMemDC = CreateCompatibleDC(hDC);  
  29.         if (NULL == m_hMemDC) return;  
  30.         ReleaseDC(m_pHGE->System_GetState(HGE_HWND),hDC);  
  31.   
  32.         ::SetMapMode(m_hMemDC, MM_TEXT);  
  33.         ::SetTextColor(m_hMemDC,RGB(255,255,255));  
  34.         ::SetBkColor(m_hMemDC,RGB(0,0,0));  
  35.   
  36.         m_hFont = CreateFont(  
  37.             -nFaceSize,  
  38.             0,  
  39.             0,  
  40.             0,  
  41.             (bBold) ? FW_BOLD : FW_NORMAL,  
  42.             bItalic,  
  43.             FALSE,  
  44.             FALSE,  
  45.             DEFAULT_CHARSET,  
  46.             OUT_DEFAULT_PRECIS,  
  47.             CLIP_DEFAULT_PRECIS,  
  48.             DEFAULT_QUALITY,  
  49.             FF_DONTCARE | DEFAULT_PITCH,  
  50.             lpsFontName);  
  51.         if (NULL == (m_hFont)) return;  
  52.         SelectObject(m_hMemDC, m_hFont);  
  53.   
  54.         memset(m_Glyphs,0,sizeof(TENGINEFONTGLYPH)*font_count);  
  55.   
  56.         m_nAntialias    = bAntialias ? GGO_GRAY8_BITMAP : GGO_BITMAP;  
  57.   
  58.         TEXTMETRIC tm;  
  59.         ::GetTextMetrics(m_hMemDC,&tm);  
  60.         m_nAscent        = tm.tmAscent;  
  61.   
  62.         m_nFontSize        = static_cast<float>(nFaceSize);  
  63.         m_nKerningWidth    = 0;  
  64.         m_nKerningHeight= 0;  
  65.   
  66.         m_pSprite = new hgeSprite(0, 0, 0, 0, 0);  
  67.         m_pSprite->SetColor(ARGB(255, 255, 255, 255));  
  68.     }  
  69.     ~GfxFont(void)  
  70.     {  
  71.         for (int nIdx = 0; nIdx < font_count; ++nIdx)  
  72.         { if (m_Glyphs[nIdx].t) m_pHGE->Texture_Free(m_Glyphs[nIdx].t); }  
  73.   
  74.         if ((m_hFont)) DeleteObject(m_hFont);  
  75.         if ((m_hMemDC)) DeleteDC(m_hMemDC);  
  76.   
  77.         if(m_pSprite) delete m_pSprite;  
  78.         if(m_pHGE) m_pHGE->Release();  
  79.     }  
  80.   
  81. public:  
  82.     // 渲染文本   
  83.     virtual void    Print( float x, float y, const char *format, ... )  
  84.     {  
  85.         char sBuffer[10240] = {0};  
  86.         char *lpsArg=(char*)&format+sizeof(format);  
  87.         vsprintf_s(sBuffer,10240, format,lpsArg);  
  88.         Render(x,y,CA2W(sBuffer));  
  89.     }  
  90.     virtual void    Render(float x, float y, const wchar_t* text )  
  91.     {  
  92.         float offsetX = x;  
  93.         float offsetY = y;  
  94.   
  95.         while(*text)  
  96.         {  
  97.             if (*text == L'\n' || *text == L'\r')  
  98.             {  
  99.                 offsetX = x;  
  100.                 offsetY += (m_nFontSize + m_nKerningHeight);  
  101.             }  
  102.             else  
  103.             {  
  104.                 unsigned int idx = GetGlyphByCharacter(*text);  
  105.                 if (idx > 0)  
  106.                 {  
  107.                     m_pSprite->SetTexture(m_Glyphs[idx].t);  
  108.                     m_pSprite->SetTextureRect(0, 0, m_Glyphs[idx].w, m_Glyphs[idx].h);  
  109.                     m_pSprite->Render(offsetX - m_Glyphs[idx].x, offsetY - m_Glyphs[idx].y);  
  110.                     offsetX += (GetWidthFromCharacter(*text) + m_nKerningWidth);  
  111.                 }  
  112.                 else  
  113.                 {  
  114.                     offsetX += (GetWidthFromCharacter(*text) + m_nKerningWidth);  
  115.                 }  
  116.             }  
  117.   
  118.             ++text;  
  119.         }  
  120.     }  
  121.   
  122.     // 设置与获取颜色   
  123.     virtual void    SetColor( DWORD dwColor, int i = -1 )  
  124.     {  
  125.         m_pSprite->SetColor(dwColor,i);  
  126.     }  
  127.     virtual DWORD    GetColor( int i = 0 )  
  128.     {  
  129.         return m_pSprite->GetColor(i);  
  130.     }  
  131.   
  132.     // 获取文本宽高   
  133.     virtual SIZE    GetTextSize( const wchar_t* text )  
  134.     {  
  135.         SIZE dim = {0, static_cast<LONG>(m_nFontSize)};  
  136.         float nRowWidth = 0;  
  137.   
  138.         while(*text)  
  139.         {  
  140.             if (*text == L'\n' || *text == L'\r')  
  141.             {  
  142.                 dim.cy += static_cast<LONG>(m_nFontSize + m_nKerningHeight);  
  143.                 if (dim.cx < static_cast<LONG>(nRowWidth))  
  144.                     dim.cx = static_cast<LONG>(nRowWidth);  
  145.                 nRowWidth = 0;  
  146.             }  
  147.             else  
  148.                 nRowWidth += (GetWidthFromCharacter(*text) + m_nKerningWidth);  
  149.             ++text;  
  150.         }  
  151.   
  152.         if (dim.cx < static_cast<LONG>(nRowWidth))  
  153.             dim.cx = static_cast<LONG>(nRowWidth);  
  154.   
  155.         return dim;  
  156.     }  
  157.   
  158.     // 根据坐标获取字符   
  159.     virtual wchar_t    GetCharacterFromPos( const wchar_t* text, float pixel_x, float pixel_y )  
  160.     {  
  161.         float x = 0;  
  162.         float y = 0;  
  163.   
  164.         while (*text)  
  165.         {  
  166.             if (*text == L'\n' || *text == L'\r')  
  167.             {  
  168.                 x = 0;  
  169.                 y += (m_nFontSize+m_nKerningHeight);  
  170.                 text++;  
  171.   
  172.                 if (!(*text))  
  173.                     break;  
  174.             }  
  175.   
  176.             float w = GetWidthFromCharacter(*text);  
  177.             if (pixel_x > x && pixel_x <= x + w &&  
  178.                 pixel_y > y && pixel_y <= y + m_nFontSize)  
  179.                 return *text;  
  180.   
  181.             x += (w+m_nKerningWidth);  
  182.   
  183.             text++;  
  184.         }  
  185.   
  186.         return L'\0';  
  187.     }  
  188.   
  189.     // 设置字间距   
  190.     virtual void    SetKerningWidth( float kerning )  
  191.     {  
  192.         m_nKerningWidth = kerning;  
  193.     }  
  194.     virtual void    SetKerningHeight( float kerning )  
  195.     {  
  196.         m_nKerningHeight = kerning;  
  197.     }  
  198.   
  199.     // 获取字间距   
  200.     virtual float    GetKerningWidth()  
  201.     {  
  202.         return m_nKerningWidth;  
  203.     }  
  204.     virtual float    GetKerningHeight()  
  205.     {  
  206.         return m_nKerningHeight;  
  207.     }  
  208.   
  209.     // 字体大小   
  210.     virtual float    GetFontSize()  
  211.     {  
  212.         return m_nFontSize;  
  213.     }  
  214.   
  215. private:  
  216.     // 根据字符获取轮廓   
  217.     unsigned int    GetGlyphByCharacter( wchar_t c )  
  218.     {  
  219.         unsigned int idx = (unsigned int)c;  
  220.         if (NULL == (m_Glyphs[idx].t)) CacheCharacter(idx,c);  
  221.         return idx;  
  222.     }  
  223.     inline float    GetWidthFromCharacter( wchar_t c, bool original = false )  
  224.     {  
  225.         unsigned int idx = GetGlyphByCharacter(c);  
  226.         if (original && idx > 0 && idx < font_count) return m_Glyphs[idx].c;  
  227.         return    (idx >= 0x2000) ? m_nFontSize : _floor(m_nFontSize / 2);  
  228.     }  
  229.     inline void        CacheCharacter(unsigned int idx, wchar_t c)  
  230.     {  
  231.         if (idx < font_count && NULL == m_Glyphs[idx].t)  
  232.         {  
  233.             UINT nChar = (UINT)c;  
  234.   
  235.             MAT2 mat2 = {{0,1},{0,0},{0,0},{0,1}};  
  236.             GLYPHMETRICS gm;  
  237.             DWORD nLen = ::GetGlyphOutlineW(m_hMemDC,nChar,m_nAntialias,&gm,0,NULL,&mat2);  
  238.   
  239.             HTEXTURE hTex = m_pHGE->Texture_Create(gm.gmBlackBoxX,gm.gmBlackBoxY);  
  240.             if (NULL == hTex) return;  
  241.   
  242.             if((signed)nLen > 0)  
  243.             {  
  244.                 LPBYTE lpBuf = new BYTE[nLen];  
  245.   
  246.                 if (nLen == ::GetGlyphOutlineW(m_hMemDC,nChar,m_nAntialias,&gm,nLen,lpBuf,&mat2))  
  247.                 {  
  248.                     BYTE*    lpSrc = lpBuf;  
  249.                     DWORD*    lpDst = m_pHGE->Texture_Lock(hTex,FALSE);  
  250.   
  251.                     if (GGO_BITMAP == m_nAntialias)  
  252.                     {  
  253.                         LONG nSrcPitch = (gm.gmBlackBoxX / 32 + (gm.gmBlackBoxX % 32 == 0 ? 0 : 1)) * 4;  
  254.                         LONG nDstPitch = m_pHGE->Texture_GetWidth(hTex);  
  255.   
  256.                         for (UINT y = 0; y < gm.gmBlackBoxY; ++y)  
  257.                         {  
  258.                             for (UINT x = 0; x < gm.gmBlackBoxX; ++x)  
  259.                             {  
  260.                                 for(UINT k = 0; k < 8; ++k)     
  261.                                 {  
  262.                                     UINT i = 8 * x + k;  
  263.                                     if (i >= gm.gmBlackBoxX)  
  264.                                     {  
  265.                                         x+=7;  
  266.                                         break;  
  267.                                     }  
  268.                                     lpDst[i] = ((lpSrc[x] >> (7 - k)) & 1) ? 0xFFFFFFFF : 0x0;  
  269.                                 }  
  270.                             }  
  271.   
  272.                             lpSrc += nSrcPitch;  
  273.                             lpDst += nDstPitch;  
  274.                         }  
  275.                     }  
  276.                     else  
  277.                     {  
  278.                         LONG nSrcPitch = (gm.gmBlackBoxX / 4 + (gm.gmBlackBoxX % 4 == 0 ? 0 : 1)) * 4;  
  279.                         LONG nDstPitch = m_pHGE->Texture_GetWidth(hTex);  
  280.   
  281.                         for (UINT y = 0; y < gm.gmBlackBoxY; ++y)  
  282.                         {  
  283.                             for (UINT x = 0; x < gm.gmBlackBoxX; ++x)  
  284.                             {  
  285.                                 lpDst[x] = ARGB(g_byAlphaLevel[lpSrc[x]],0xFF,0xFF,0xFF);  
  286.                             }  
  287.   
  288.                             lpSrc += nSrcPitch;  
  289.                             lpDst += nDstPitch;  
  290.                         }  
  291.                     }  
  292.   
  293.                     m_pHGE->Texture_Unlock(hTex);  
  294.                 }  
  295.   
  296.                 delete lpBuf;  
  297.             }  
  298.             else  
  299.             {  
  300.                 // 非正常显示字符   
  301.             }  
  302.   
  303.             m_Glyphs[idx].t = hTex;  
  304.             m_Glyphs[idx].w = static_cast<float>(gm.gmBlackBoxX);  
  305.             m_Glyphs[idx].h = static_cast<float>(gm.gmBlackBoxY);  
  306.             m_Glyphs[idx].x = static_cast<float>(-gm.gmptGlyphOrigin.x);  
  307.             m_Glyphs[idx].y = static_cast<float>(-m_nAscent + gm.gmptGlyphOrigin.y);  
  308.             m_Glyphs[idx].c = static_cast<float>(gm.gmCellIncX);  
  309.         }  
  310.     }  
  311.   
  312.     typedef struct tagEngineFontGlyph  
  313.     {  
  314.         HTEXTURE    t;  
  315.         float        w;  
  316.         float        h;  
  317.         float        x;  
  318.         float        y;  
  319.         float        c;  
  320.     }TENGINEFONTGLYPH;  
  321.   
  322.     static const unsigned int font_count = 0xFFFF;// = sizeof(wchar_t);   
  323.     TENGINEFONTGLYPH    m_Glyphs[font_count];  
  324.     UINT                m_nAntialias;//反锯齿   
  325.     LONG                m_nAscent;//基线   
  326.     DWORD                m_dwFontColor;  
  327.     float                m_nFontSize;  
  328.     float                m_nKerningWidth;  
  329.     float                m_nKerningHeight;  
  330.   
  331.     HGE*                m_pHGE;  
  332.     hgeSprite*            m_pSprite;  
  333.   
  334.     // GDI设备   
  335.     HDC                    m_hMemDC;  
  336.     HFONT                m_hFont;  
  337. };  
  338. const unsigned char GfxFont::g_byAlphaLevel[65] =   
  339. {  
  340.     0,  4,  8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48,  
  341.     52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96,100,  
  342.     104,108,112,116,120,124,128,132,136,140,144,148,152,  
  343.     156,160,164,168,172,176,180,184,188,192,196,200,204,  
  344.     208,212,216,220,224,228,232,236,240,244,248,252,255  
  345. };  
  346.   
  347.   
  348.   
  349. #endif//GDIFONT_H 

你可能感兴趣的:(游戏开发,c/c++编程技术,C/C++经典规范源码分享)