1. #include "StdAfx.h"
  2. #include "GrpText.h"
  3. #include "../eterBase/Stl.h"
  4. #include "Util.h"
  5. CGraphicFontTexture::CGraphicFontTexture()
  6. {
  7. Initialize();
  8. }
  9. CGraphicFontTexture::~CGraphicFontTexture()
  10. {
  11. Destroy();
  12. }
  13. void CGraphicFontTexture::Initialize()
  14. {
  15. CGraphicTexture::Initialize();
  16. m_hFontOld = NULL;
  17. m_hFont = NULL;
  18. m_isDirty = false;
  19. m_bItalic = false;
  20. m_bBold = false;
  21. }
  22. bool CGraphicFontTexture::IsEmpty() const
  23. {
  24. return m_fontMap.size() == 0;
  25. }
  26. void CGraphicFontTexture::Destroy()
  27. {
  28. HDC hDC = m_dib.GetDCHandle();
  29. if (hDC)
  30. SelectObject(hDC, m_hFontOld);
  31. m_dib.Destroy();
  32. m_lpd3dTexture = NULL;
  33. CGraphicTexture::Destroy();
  34. stl_wipe(m_pFontTextureVector);
  35. m_charInfoMap.clear();
  36. if (m_fontMap.size())
  37. {
  38. TFontMap::iterator i = m_fontMap.begin();
  39. while(i != m_fontMap.end())
  40. {
  41. DeleteObject((HGDIOBJ)i->second);
  42. ++i;
  43. }
  44. m_fontMap.clear();
  45. }
  46. Initialize();
  47. }
  48. bool CGraphicFontTexture::CreateDeviceObjects()
  49. {
  50. return true;
  51. }
  52. void CGraphicFontTexture::DestroyDeviceObjects()
  53. {
  54. }
  55. bool CGraphicFontTexture::Create(const char* c_szFontName, int fontSize, bool bItalic, bool bBold)
  56. {
  57. Destroy();
  58. strncpy_s(m_fontName, c_szFontName, sizeof(m_fontName)-1);
  59. m_fontSize = fontSize;
  60. m_bItalic = bItalic;
  61. m_bBold = bBold;
  62. m_x = 0;
  63. m_y = 0;
  64. m_step = 0;
  65. DWORD width = 256,height = 256;
  66. if (GetMaxTextureWidth() > 512)
  67. width = 512;
  68. if (GetMaxTextureHeight() > 512)
  69. height = 512;
  70. if (!m_dib.Create(ms_hDC, width, height))
  71. return false;
  72. HDC hDC = m_dib.GetDCHandle();
  73. m_hFont = GetFont(GetDefaultCodePage());
  74. m_hFontOld=(HFONT)SelectObject(hDC, m_hFont);
  75. SetTextColor(hDC, RGB(255, 255, 255));
  76. SetBkColor(hDC, 0);
  77. if (!AppendTexture())
  78. return false;
  79. return true;
  80. }
  81. HFONT CGraphicFontTexture::GetFont(WORD codePage)
  82. {
  83. HFONT hFont = NULL;
  84. TFontMap::iterator i = m_fontMap.find(codePage);
  85. if(i != m_fontMap.end())
  86. {
  87. hFont = i->second;
  88. }
  89. else
  90. {
  91. LOGFONT logFont;
  92. memset(&logFont, 0, sizeof(LOGFONT));
  93. logFont.lfHeight = m_fontSize;
  94. logFont.lfEscapement = 0;
  95. logFont.lfOrientation = 0;
  96. logFont.lfWeight = (m_bBold) ? FW_BOLD : FW_NORMAL;
  97. logFont.lfItalic = (BYTE) m_bItalic;
  98. logFont.lfUnderline = FALSE;
  99. logFont.lfStrikeOut = FALSE;
  100. logFont.lfCharSet = GetCharsetFromCodePage(codePage);
  101. logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
  102. logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  103. logFont.lfQuality = ANTIALIASED_QUALITY;
  104. logFont.lfPitchAndFamily = VARIABLE_PITCH;
  105. //Tracenf("font: %s", GetFontFaceFromCodePage(codePage));
  106. strcpy(logFont.lfFaceName, m_fontName); //GetFontFaceFromCodePage(codePage));
  107. //strcpy(logFont.lfFaceName, GetFontFaceFromCodePage(codePage));
  108. hFont = CreateFontIndirect(&logFont);
  109. m_fontMap.insert(TFontMap::value_type(codePage, hFont));
  110. }
  111. return hFont;
  112. }
  113. bool CGraphicFontTexture::AppendTexture()
  114. {
  115. CGraphicImageTexture * pNewTexture = new CGraphicImageTexture;
  116. if (!pNewTexture->Create(m_dib.GetWidth(), m_dib.GetHeight(), D3DFMT_A4R4G4B4))
  117. {
  118. delete pNewTexture;
  119. return false;
  120. }
  121. m_pFontTextureVector.push_back(pNewTexture);
  122. return true;
  123. }
  124. bool CGraphicFontTexture::UpdateTexture()
  125. {
  126. if(!m_isDirty)
  127. return true;
  128. m_isDirty = false;
  129. CGraphicImageTexture * pFontTexture = m_pFontTextureVector.back();
  130. if (!pFontTexture)
  131. return false;
  132. WORD* pwDst;
  133. int pitch;
  134. if (!pFontTexture->Lock(&pitch, (void**)&pwDst))
  135. return false;
  136. pitch /= 2;
  137. int width = m_dib.GetWidth();
  138. int height = m_dib.GetHeight();
  139. DWORD * pdwSrc = (DWORD*)m_dib.GetPointer();
  140. for (int y = 0; y < height; ++y, pwDst += pitch, pdwSrc += width)
  141. for (int x = 0; x < width; ++x)
  142. pwDst[x]=pdwSrc[x];
  143. pFontTexture->Unlock();
  144. return true;
  145. }
  146. CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::GetCharacterInfomation(WORD codePage, wchar_t keyValue)
  147. {
  148. TCharacterKey code(codePage, keyValue);
  149. TCharacterInfomationMap::iterator f = m_charInfoMap.find(code);
  150. if (m_charInfoMap.end() == f)
  151. {
  152. return UpdateCharacterInfomation(code);
  153. }
  154. else
  155. {
  156. return &f->second;
  157. }
  158. }
  159. CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::UpdateCharacterInfomation(TCharacterKey code)
  160. {
  161. HDC hDC = m_dib.GetDCHandle();
  162. SelectObject(hDC, GetFont(code.first));
  163. wchar_t keyValue = code.second;
  164. if (keyValue == 0x08)
  165. keyValue = L' '; // 탭은 공백으로 바꾼다 (아랍 출력시 탭 사용: NAME:\tTEXT -> TEXT\t:NAME 로 전환됨 )
  166. ABCFLOAT stABC;
  167. SIZE size;
  168. if (!GetTextExtentPoint32W(hDC, &keyValue, 1, &size) || !GetCharABCWidthsFloatW(hDC, keyValue, keyValue, &stABC))
  169. return NULL;
  170. size.cx = stABC.abcfB;
  171. if( stABC.abcfA > 0.0f )
  172. size.cx += ceilf(stABC.abcfA);
  173. if( stABC.abcfC > 0.0f )
  174. size.cx += ceilf(stABC.abcfC);
  175. size.cx++;
  176. LONG lAdvance = ceilf( stABC.abcfA + stABC.abcfB + stABC.abcfC );
  177. int width = m_dib.GetWidth();
  178. int height = m_dib.GetHeight();
  179. if (m_x + size.cx >= (width - 1))
  180. {
  181. m_y += (m_step + 1);
  182. m_step = 0;
  183. m_x = 0;
  184. if (m_y + size.cy >= (height - 1))
  185. {
  186. if (!UpdateTexture())
  187. {
  188. return NULL;
  189. }
  190. if (!AppendTexture())
  191. return NULL;
  192. m_y = 0;
  193. }
  194. }
  195. TextOutW(hDC, m_x, m_y, &keyValue, 1);
  196. int nChrX;
  197. int nChrY;
  198. int nChrWidth = size.cx;
  199. int nChrHeight = size.cy;
  200. int nDIBWidth = m_dib.GetWidth();
  201. DWORD*pdwDIBData=(DWORD*)m_dib.GetPointer();
  202. DWORD*pdwDIBBase=pdwDIBData+nDIBWidth*m_y+m_x;
  203. DWORD*pdwDIBRow;
  204. pdwDIBRow=pdwDIBBase;
  205. for (nChrY=0; nChrY<nChrHeight; ++nChrY, pdwDIBRow+=nDIBWidth)
  206. {
  207. for (nChrX=0; nChrX<nChrWidth; ++nChrX)
  208. {
  209. pdwDIBRow[nChrX]=(pdwDIBRow[nChrX]&0xff) ? 0xffff : 0;
  210. }
  211. }
  212. float rhwidth = 1.0f / float(width);
  213. float rhheight = 1.0f / float(height);
  214. TCharacterInfomation& rNewCharInfo = m_charInfoMap[code];
  215. rNewCharInfo.index = m_pFontTextureVector.size() - 1;
  216. rNewCharInfo.width = size.cx;
  217. rNewCharInfo.height = size.cy;
  218. rNewCharInfo.left = float(m_x) * rhwidth;
  219. rNewCharInfo.top = float(m_y) * rhheight;
  220. rNewCharInfo.right = float(m_x+size.cx) * rhwidth;
  221. rNewCharInfo.bottom = float(m_y+size.cy) * rhheight;
  222. rNewCharInfo.advance = (float) lAdvance;
  223. m_x += size.cx;
  224. if (m_step < size.cy)
  225. m_step = size.cy;
  226. m_isDirty = true;
  227. return &rNewCharInfo;
  228. }
  229. bool CGraphicFontTexture::CheckTextureIndex(DWORD dwTexture)
  230. {
  231. if (dwTexture >= m_pFontTextureVector.size())
  232. return false;
  233. return true;
  234. }
  235. void CGraphicFontTexture::SelectTexture(DWORD dwTexture)
  236. {
  237. assert(CheckTextureIndex(dwTexture));
  238. m_lpd3dTexture = m_pFontTextureVector[dwTexture]->GetD3DTexture();
  239. }