GfxFont.cpp
上传用户:jalin138
上传日期:2022-02-12
资源大小:5720k
文件大小:7k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. #include "GfxFont.h"
  2.  
  3. #include <atlbase.h>
  4. #include <stdio.h>
  5. #include   <wchar.h> 
  6. #include   <atlconv.h> 
  7. #pragma  comment(lib,"Gdi32.lib")
  8. __inline float _floor(float f)
  9. {
  10. static int _n;
  11. _asm fld f
  12. _asm fistp _n
  13. return (float)_n;
  14. }
  15. // 65级灰度表
  16. const unsigned char g_byAlphaLevel[65] = 
  17. {
  18.   0,  4,  8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48,
  19.  52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96,100,
  20. 104,108,112,116,120,124,128,132,136,140,144,148,152,
  21. 156,160,164,168,172,176,180,184,188,192,196,200,204,
  22. 208,212,216,220,224,228,232,236,240,244,248,252,255
  23. };
  24. GfxFont::GfxFont(const char* lpsFontName, int nFaceSize, BOOL bBold, BOOL bItalic, BOOL bAntialias)
  25. {
  26. m_pHGE = hgeCreate(HGE_VERSION);
  27. // 创建GDI相关设备
  28. HDC hDC = GetDC(m_pHGE->System_GetState(HGE_HWND));
  29. m_hMemDC = CreateCompatibleDC(hDC);
  30. if (NULL == m_hMemDC) return;
  31. ReleaseDC(m_pHGE->System_GetState(HGE_HWND),hDC);
  32. ::SetMapMode(m_hMemDC, MM_TEXT);
  33. ::SetTextColor(m_hMemDC,RGB(255,255,255));
  34. ::SetBkColor(m_hMemDC,RGB(0,0,0));
  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. memset(m_Glyphs,0,sizeof(TENGINEFONTGLYPH)*font_count);
  53. m_nAntialias = bAntialias ? GGO_GRAY8_BITMAP : GGO_BITMAP;
  54. TEXTMETRIC tm;
  55. ::GetTextMetrics(m_hMemDC,&tm);
  56. m_nAscent = tm.tmAscent;
  57. m_nFontSize = static_cast<float>(nFaceSize);
  58. m_nKerningWidth = 0;
  59. m_nKerningHeight= 0;
  60. m_pSprite = new hgeSprite(0, 0, 0, 0, 0);
  61. m_pSprite->SetColor(ARGB(255, 255, 255, 255));
  62. }
  63. GfxFont::~GfxFont(void)
  64. {
  65. for (int nIdx = 0; nIdx < font_count; ++nIdx)
  66. { if (m_Glyphs[nIdx].t) m_pHGE->Texture_Free(m_Glyphs[nIdx].t); }
  67. if ((m_hFont)) DeleteObject(m_hFont);
  68. if ((m_hMemDC)) DeleteDC(m_hMemDC);
  69. if(m_pSprite) delete m_pSprite;
  70. if(m_pHGE) m_pHGE->Release();
  71. }
  72. // 渲染文本
  73. void GfxFont::Print( float x, float y, const char *format, ... )
  74. {
  75. char sBuffer[10240] = {0};
  76. char *lpsArg=(char*)&format+sizeof(format);
  77. vsprintf(sBuffer, format, lpsArg);
  78. USES_CONVERSION;
  79. Render(x,y,A2W(sBuffer));
  80. }
  81. void GfxFont::Render(float x, float y, const wchar_t* text )
  82. {
  83. float offsetX = x;
  84. float offsetY = y;
  85. while(*text)
  86. {
  87. if (*text == L'n' || *text == L'r')
  88. {
  89. offsetX = x;
  90. offsetY += (m_nFontSize + m_nKerningHeight);
  91. }
  92. else
  93. {
  94. unsigned int idx = GetGlyphByCharacter(*text);
  95. if (idx > 0)
  96. {
  97. m_pSprite->SetTexture(m_Glyphs[idx].t);
  98. m_pSprite->SetTextureRect(0, 0, m_Glyphs[idx].w, m_Glyphs[idx].h);
  99. m_pSprite->Render(offsetX - m_Glyphs[idx].x, offsetY - m_Glyphs[idx].y);
  100. offsetX += (GetWidthFromCharacter(*text) + m_nKerningWidth);
  101. }
  102. else
  103. {
  104. offsetX += (GetWidthFromCharacter(*text) + m_nKerningWidth);
  105. }
  106. }
  107. ++text;
  108. }
  109. }
  110. // 设置与获取颜色
  111. void GfxFont::SetColor( DWORD dwColor, int i )
  112. {
  113. m_pSprite->SetColor(dwColor,i);
  114. }
  115. DWORD GfxFont::GetColor(int i)
  116. {
  117. return m_pSprite->GetColor(i);
  118. }
  119. // 获取文本宽高
  120. SIZE GfxFont::GetTextSize( const wchar_t* text )
  121. {
  122. SIZE dim = {0, static_cast<LONG>(m_nFontSize)};
  123. float nRowWidth = 0;
  124. while(*text)
  125. {
  126. if (*text == L'n' || *text == L'r')
  127. {
  128. dim.cy += static_cast<LONG>(m_nFontSize + m_nKerningHeight);
  129. if (dim.cx < static_cast<LONG>(nRowWidth))
  130. dim.cx = static_cast<LONG>(nRowWidth);
  131. nRowWidth = 0;
  132. }
  133. else
  134. nRowWidth += (GetWidthFromCharacter(*text) + m_nKerningWidth);
  135. ++text;
  136. }
  137. if (dim.cx < static_cast<LONG>(nRowWidth))
  138. dim.cx = static_cast<LONG>(nRowWidth);
  139. return dim;
  140. }
  141. // 根据坐标获取字符
  142. wchar_t GfxFont::GetCharacterFromPos( const wchar_t* text, float pixel_x, float pixel_y )
  143. {
  144. float x = 0;
  145. float y = 0;
  146. while (*text)
  147. {
  148. if (*text == L'n' || *text == L'r')
  149. {
  150. x = 0;
  151. y += (m_nFontSize+m_nKerningHeight);
  152. text++;
  153. if (!(*text))
  154. break;
  155. }
  156. float w = GetWidthFromCharacter(*text);
  157. if (pixel_x > x && pixel_x <= x + w &&
  158. pixel_y > y && pixel_y <= y + m_nFontSize)
  159. return *text;
  160. x += (w+m_nKerningWidth);
  161. text++;
  162. }
  163. return L'';
  164. }
  165. // 设置字间距
  166. void GfxFont::SetKerningWidth( float kerning )
  167. {
  168. m_nKerningWidth = kerning;
  169. }
  170. void GfxFont::SetKerningHeight( float kerning )
  171. {
  172. m_nKerningHeight = kerning;
  173. }
  174. // 获取字间距
  175. float GfxFont::GetKerningWidth()
  176. {
  177. return m_nKerningWidth;
  178. }
  179. float GfxFont::GetKerningHeight()
  180. {
  181. return m_nKerningHeight;
  182. }
  183. // 字体大小
  184. float GfxFont::GetFontSize()
  185. {
  186. return m_nFontSize;
  187. }
  188. // 根据字符获取轮廓
  189. unsigned int GfxFont::GetGlyphByCharacter( wchar_t c )
  190. {
  191. unsigned int idx = (unsigned int)c;
  192. if (NULL == (m_Glyphs[idx].t)) CacheCharacter(idx,c);
  193. return idx;
  194. }
  195. inline float GfxFont::GetWidthFromCharacter( wchar_t c, bool original )
  196. {
  197. unsigned int idx = GetGlyphByCharacter(c);
  198. if (original && idx > 0 && idx < font_count) return m_Glyphs[idx].c;
  199. return (idx >= 0x2000) ? m_nFontSize : _floor(m_nFontSize / 2);
  200. }
  201. inline void GfxFont::CacheCharacter(unsigned int idx, wchar_t c)
  202. {
  203. if (idx < font_count && NULL == m_Glyphs[idx].t)
  204. {
  205. UINT nChar = (UINT)c;
  206. MAT2 mat2 = {{0,1},{0,0},{0,0},{0,1}};
  207. GLYPHMETRICS gm;
  208. DWORD nLen = ::GetGlyphOutlineW(m_hMemDC,nChar,m_nAntialias,&gm,0,NULL,&mat2);
  209. HTEXTURE hTex = m_pHGE->Texture_Create(gm.gmBlackBoxX,gm.gmBlackBoxY);
  210. if (NULL == hTex) return;
  211. if((signed)nLen > 0)
  212. {
  213. LPBYTE lpBuf = new BYTE[nLen];
  214. if (nLen == ::GetGlyphOutlineW(m_hMemDC,nChar,m_nAntialias,&gm,nLen,lpBuf,&mat2))
  215. {
  216. BYTE* lpSrc = lpBuf;
  217. DWORD* lpDst = m_pHGE->Texture_Lock(hTex,FALSE);
  218. if (GGO_BITMAP == m_nAntialias)
  219. {
  220. LONG nSrcPitch = (gm.gmBlackBoxX / 32 + (gm.gmBlackBoxX % 32 == 0 ? 0 : 1)) * 4;
  221. LONG nDstPitch = m_pHGE->Texture_GetWidth(hTex);
  222. for (UINT y = 0; y < gm.gmBlackBoxY; ++y)
  223. {
  224. for (UINT x = 0; x < gm.gmBlackBoxX; ++x)
  225. {
  226. for(UINT k = 0; k < 8; ++k)   
  227. {
  228. UINT i = 8 * x + k;
  229. if (i >= gm.gmBlackBoxX)
  230. {
  231. x+=7;
  232. break;
  233. }
  234. lpDst[i] = ((lpSrc[x] >> (7 - k)) & 1) ? 0xFFFFFFFF : 0x0;
  235. }
  236. }
  237. lpSrc += nSrcPitch;
  238. lpDst += nDstPitch;
  239. }
  240. }
  241. else
  242. {
  243. LONG nSrcPitch = (gm.gmBlackBoxX / 4 + (gm.gmBlackBoxX % 4 == 0 ? 0 : 1)) * 4;
  244. LONG nDstPitch = m_pHGE->Texture_GetWidth(hTex);
  245. for (UINT y = 0; y < gm.gmBlackBoxY; ++y)
  246. {
  247. for (UINT x = 0; x < gm.gmBlackBoxX; ++x)
  248. {
  249. lpDst[x] = ARGB(g_byAlphaLevel[lpSrc[x]],0xFF,0xFF,0xFF);
  250. }
  251. lpSrc += nSrcPitch;
  252. lpDst += nDstPitch;
  253. }
  254. }
  255. m_pHGE->Texture_Unlock(hTex);
  256. }
  257. delete lpBuf;
  258. }
  259. else
  260. {
  261. // 非正常显示字符
  262. }
  263. m_Glyphs[idx].t = hTex;
  264. m_Glyphs[idx].w = static_cast<float>(gm.gmBlackBoxX);
  265. m_Glyphs[idx].h = static_cast<float>(gm.gmBlackBoxY);
  266. m_Glyphs[idx].x = static_cast<float>(-gm.gmptGlyphOrigin.x);
  267. m_Glyphs[idx].y = static_cast<float>(-m_nAscent + gm.gmptGlyphOrigin.y);
  268. m_Glyphs[idx].c = static_cast<float>(gm.gmCellIncX);
  269. }
  270. }