HGE-8 HGE的中文显示

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

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

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

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

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

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

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

 直接复制源码保存为gfxfont.h并引入工程后即可使用.

使用方法:

 本方法是为解决HGE项目中支持中文显示的新方案。

 本解决方案不需要依赖任何图片字模,并支持丰富的显示方法。

 使用方法很简单,只需如下几步即可:

  一、包含 "gfxFont.h" 头文件。

  二、创建字体指针:GfxFont* fontspr = new GfxFont(字体名,字体大小,是否粗体,是否斜体,是否平滑模式);

  三、文本颜色:fontspr->SetColor(ARGB);

  三、文本渲染:fontspr->Print(坐标x,坐标y,文本内容);

  四、销毁字体:当程序结束时,使用 delete fontspr; 来销毁字体。

---微妙的平衡

 

 

posted @ 2012-08-02 20:04  Kinel  阅读(1584)  评论(0编辑  收藏  举报