HGE本身并不支持中文的显示,因此我使用由 微妙的平衡 大神提供的解决方案.
大神提供的代码本来包含gfxfont.h和gfxfont.cpp文件,只需要将这两个文件添加到工程中即可使用.
但是我实在太懒,为了避免每次都添加两个文件到工程中去,于是我擅自将cpp的代码全部移到了.h文件中并做了一些细微的改动.
这样每次使用的时候就只需要将gfxfont.h引入工程就够了,当然我把这个gfxfont.h直接放到了hge的include文件夹中,这样我就可以直接
用#include
以下是gfxfont.h文件的源码:
gfxfont.h
1 #ifndef GDIFONT_H 2 #define GDIFONT_H 3 4 #include5 #include 6 #include 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 (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 (m_nFontSize + m_nKerningHeight); 142 if (dim.cx < static_cast (nRowWidth)) 143 dim.cx = static_cast (nRowWidth); 144 nRowWidth = 0; 145 } 146 else 147 nRowWidth += (GetWidthFromCharacter(*text) + m_nKerningWidth); 148 ++text; 149 } 150 151 if (dim.cx < static_cast (nRowWidth)) 152 dim.cx = static_cast (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; 来销毁字体。
---微妙的平衡