Advertisement
Guest User

GrpTextInstance.cpp

a guest
Oct 17th, 2021
371
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.55 KB | None | 0 0
  1. #include "StdAfx.h"
  2. #include "GrpTextInstance.h"
  3. #include "StateManager.h"
  4. #include "IME.h"
  5. #include "TextTag.h"
  6. #include "../EterLocale/StringCodec.h"
  7. #include "../EterBase/Utils.h"
  8. #include "../EterLocale/Arabic.h"
  9. #include "ResourceManager.h"
  10.  
  11. extern DWORD GetDefaultCodePage();
  12.  
  13. const float c_fFontFeather = 0.5f;
  14.  
  15. CDynamicPool<CGraphicTextInstance> CGraphicTextInstance::ms_kPool;
  16.  
  17. static int gs_mx = 0;
  18. static int gs_my = 0;
  19.  
  20. static std::wstring gs_hyperlinkText;
  21.  
  22. void CGraphicTextInstance::Hyperlink_UpdateMousePos(int x, int y)
  23. {
  24. gs_mx = x;
  25. gs_my = y;
  26. gs_hyperlinkText = L"";
  27. }
  28.  
  29. int CGraphicTextInstance::Hyperlink_GetText(char* buf, int len)
  30. {
  31. if (gs_hyperlinkText.empty())
  32. return 0;
  33.  
  34. int codePage = GetDefaultCodePage();
  35.  
  36. return Ymir_WideCharToMultiByte(codePage, 0, gs_hyperlinkText.c_str(), gs_hyperlinkText.length(), buf, len, NULL, NULL);
  37. }
  38.  
  39. int CGraphicTextInstance::__DrawCharacter(CGraphicFontTexture * pFontTexture, WORD codePage, wchar_t text, DWORD dwColor)
  40. {
  41. CGraphicFontTexture::TCharacterInfomation* pInsCharInfo = pFontTexture->GetCharacterInfomation(codePage, text);
  42.  
  43. if (pInsCharInfo)
  44. {
  45. m_dwColorInfoVector.push_back(dwColor);
  46. m_pCharInfoVector.push_back(pInsCharInfo);
  47.  
  48. m_textWidth += pInsCharInfo->advance;
  49. m_textHeight = max(pInsCharInfo->height, m_textHeight);
  50. return pInsCharInfo->advance;
  51. }
  52.  
  53. return 0;
  54. }
  55.  
  56. void CGraphicTextInstance::__GetTextPos(DWORD index, float* x, float* y)
  57. {
  58. index = min(index, m_pCharInfoVector.size());
  59.  
  60. float sx = 0;
  61. float sy = 0;
  62. float fFontMaxHeight = 0;
  63.  
  64. for(DWORD i=0; i<index; ++i)
  65. {
  66. if (sx+float(m_pCharInfoVector[i]->width) > m_fLimitWidth)
  67. {
  68. sx = 0;
  69. sy += fFontMaxHeight;
  70. }
  71.  
  72. sx += float(m_pCharInfoVector[i]->advance);
  73. fFontMaxHeight = max(float(m_pCharInfoVector[i]->height), fFontMaxHeight);
  74. }
  75.  
  76. *x = sx;
  77. *y = sy;
  78. }
  79.  
  80. bool isNumberic(const char chr)
  81. {
  82. if (chr >= '0' && chr <= '9')
  83. return true;
  84. return false;
  85. }
  86.  
  87. bool IsValidToken(const char* iter)
  88. {
  89. return iter[0]=='@' &&
  90. isNumberic(iter[1]) &&
  91. isNumberic(iter[2]) &&
  92. isNumberic(iter[3]) &&
  93. isNumberic(iter[4]);
  94. }
  95.  
  96. const char* FindToken(const char* begin, const char* end)
  97. {
  98. while(begin < end)
  99. {
  100. begin = std::find(begin, end, '@');
  101.  
  102. if(end-begin>5 && IsValidToken(begin))
  103. {
  104. return begin;
  105. }
  106. else
  107. {
  108. ++begin;
  109. }
  110. }
  111.  
  112. return end;
  113. }
  114.  
  115. int ReadToken(const char* token)
  116. {
  117. int nRet = (token[1]-'0')*1000 + (token[2]-'0')*100 + (token[3]-'0')*10 + (token[4]-'0');
  118. if (nRet == 9999)
  119. return CP_UTF8;
  120. return nRet;
  121. }
  122.  
  123. void CGraphicTextInstance::Update()
  124. {
  125. if (m_isUpdate) // 문자열이 바뀌었을 때만 업데이트 한다.
  126. return;
  127.  
  128. if (m_roText.IsNull())
  129. {
  130. Tracef("CGraphicTextInstance::Update - 폰트가 설정되지 않았습니다\n");
  131. return;
  132. }
  133.  
  134. if (m_roText->IsEmpty())
  135. return;
  136.  
  137. CGraphicFontTexture* pFontTexture = m_roText->GetFontTexturePointer();
  138. if (!pFontTexture)
  139. return;
  140.  
  141. UINT defCodePage = GetDefaultCodePage();
  142.  
  143. UINT dataCodePage = defCodePage; // 아랍 및 베트남 내부 데이터를 UTF8 을 사용하려 했으나 실패
  144.  
  145. CGraphicFontTexture::TCharacterInfomation* pSpaceInfo = pFontTexture->GetCharacterInfomation(dataCodePage, ' ');
  146.  
  147. int spaceHeight = pSpaceInfo ? pSpaceInfo->height : 12;
  148.  
  149. m_pCharInfoVector.clear();
  150. m_dwColorInfoVector.clear();
  151. m_hyperlinkVector.clear();
  152. if (m_emojiVector.size() != 0)
  153. {
  154. for (std::vector<SEmoji>::iterator itor = m_emojiVector.begin(); itor != m_emojiVector.end(); ++itor)
  155. {
  156. SEmoji & rEmo = *itor;
  157. if (rEmo.pInstance)
  158. {
  159. CGraphicImageInstance::Delete(rEmo.pInstance);
  160. rEmo.pInstance = NULL;
  161. }
  162. }
  163. }
  164. m_emojiVector.clear();
  165.  
  166. m_textWidth = 0;
  167. m_textHeight = spaceHeight;
  168.  
  169. /* wstring begin */
  170.  
  171. const char* begin = m_stText.c_str();
  172. const char* end = begin + m_stText.length();
  173.  
  174. int wTextMax = (end - begin) * 2;
  175. wchar_t* wText = (wchar_t*)_alloca(sizeof(wchar_t)*wTextMax);
  176.  
  177. DWORD dwColor = m_dwTextColor;
  178.  
  179. /* wstring end */
  180. while (begin < end)
  181. {
  182. const char * token = FindToken(begin, end);
  183.  
  184. int wTextLen = Ymir_MultiByteToWideChar(dataCodePage, 0, begin, token - begin, wText, wTextMax);
  185.  
  186. if (m_isSecret)
  187. {
  188. for(int i=0; i<wTextLen; ++i)
  189. __DrawCharacter(pFontTexture, dataCodePage, '*', dwColor);
  190. }
  191. else
  192. {
  193. if (defCodePage == CP_ARABIC) // ARABIC
  194. {
  195.  
  196. wchar_t* wArabicText = (wchar_t*)_alloca(sizeof(wchar_t) * wTextLen);
  197. int wArabicTextLen = Arabic_MakeShape(wText, wTextLen, wArabicText, wTextLen);
  198.  
  199. bool isEnglish = true;
  200. int nEnglishBase = wArabicTextLen - 1;
  201.  
  202. //<<하이퍼 링크>>
  203. int x = 0;
  204.  
  205. int len;
  206. int hyperlinkStep = 0;
  207. SHyperlink kHyperlink;
  208. std::wstring hyperlinkBuffer;
  209. int no_hyperlink = 0;
  210.  
  211. // 심볼로 끝나면 아랍어 모드로 시작해야한다
  212. if (Arabic_IsInSymbol(wArabicText[wArabicTextLen - 1]))
  213. {
  214. isEnglish = false;
  215. }
  216.  
  217. int i = 0;
  218. for (i = wArabicTextLen - 1 ; i >= 0; --i)
  219. {
  220. wchar_t wArabicChar = wArabicText[i];
  221.  
  222. if (isEnglish)
  223. {
  224.  
  225. // <<심볼의 경우 (ex. 기호, 공백)>> -> 영어 모드 유지.
  226. // <<(심볼이 아닌 것들 : 숫자, 영어, 아랍어)>>
  227. // (1) 맨 앞의 심볼 or
  228. // (2)
  229. // 1) 앞 글자가 아랍어 아님 &&
  230. // 2) 뒷 글자가 아랍어 아님 &&
  231. // 3) 뒷 글자가 심볼'|'이 아님 &&
  232. // or
  233. // (3) 현재 심볼이 '|'
  234. // <<아랍어 모드로 넘어가는 경우 : 심볼에서.>>
  235. // 1) 앞글자 아랍어
  236. // 2) 뒷글자 아랍어
  237. //
  238. //
  239. if (Arabic_IsInSymbol(wArabicChar) && (
  240. (i == 0) ||
  241. (i > 0 &&
  242. !(Arabic_HasPresentation(wArabicText, i - 1) || Arabic_IsInPresentation(wArabicText[i + 1])) && //앞글자, 뒷글자가 아랍어 아님.
  243. wArabicText[i+1] != '|'
  244. ) ||
  245. wArabicText[i] == '|'
  246. ))//if end.
  247. {
  248. // pass
  249. int temptest = 1;
  250. }
  251. // (1)아랍어이거나 (2)아랍어 다음의 심볼이라면 아랍어 모드 전환
  252. else if (Arabic_IsInPresentation(wArabicChar) || Arabic_IsInSymbol(wArabicChar))
  253. {
  254. //그 전까지의 영어를 그린다.
  255. for (int e = i + 1; e <= nEnglishBase;) {
  256. int ret = GetTextTag(&wArabicText[e], wArabicTextLen - e, len, hyperlinkBuffer);
  257.  
  258. if (ret == TEXT_TAG_PLAIN || ret == TEXT_TAG_TAG)
  259. {
  260. if (hyperlinkStep == 1)
  261. hyperlinkBuffer.append(1, wArabicText[e]);
  262. else
  263. {
  264. int charWidth = __DrawCharacter(pFontTexture, dataCodePage, wArabicText[e], dwColor);
  265. kHyperlink.ex += charWidth;
  266. //x += charWidth;
  267.  
  268. //기존 추가한 하이퍼링크의 좌표 수정.
  269. for (int j = 1; j <= no_hyperlink; j++)
  270. {
  271. if(m_hyperlinkVector.size() < j)
  272. break;
  273.  
  274. SHyperlink & tempLink = m_hyperlinkVector[m_hyperlinkVector.size() - j];
  275. tempLink.ex += charWidth;
  276. tempLink.sx += charWidth;
  277. }
  278. }
  279. }
  280. else
  281. {
  282. if (ret == TEXT_TAG_COLOR)
  283. dwColor = htoi(hyperlinkBuffer.c_str(), 8);
  284. else if (ret == TEXT_TAG_RESTORE_COLOR)
  285. dwColor = m_dwTextColor;
  286. else if (ret == TEXT_TAG_HYPERLINK_START)
  287. {
  288. hyperlinkStep = 1;
  289. hyperlinkBuffer = L"";
  290. }
  291. else if (ret == TEXT_TAG_HYPERLINK_END)
  292. {
  293. if (hyperlinkStep == 1)
  294. {
  295. ++hyperlinkStep;
  296. kHyperlink.ex = kHyperlink.sx = 0; // 실제 텍스트가 시작되는 위치
  297. }
  298. else
  299. {
  300. kHyperlink.text = hyperlinkBuffer;
  301. m_hyperlinkVector.push_back(kHyperlink);
  302. no_hyperlink++;
  303.  
  304.  
  305. hyperlinkStep = 0;
  306. hyperlinkBuffer = L"";
  307. }
  308. }
  309. }
  310. e += len;
  311. }
  312.  
  313. int charWidth = __DrawCharacter(pFontTexture, dataCodePage, Arabic_ConvSymbol(wArabicText[i]), dwColor);
  314. kHyperlink.ex += charWidth;
  315.  
  316. //기존 추가한 하이퍼링크의 좌표 수정.
  317. for (int j = 1; j <= no_hyperlink; j++)
  318. {
  319. if(m_hyperlinkVector.size() < j)
  320. break;
  321.  
  322. SHyperlink & tempLink = m_hyperlinkVector[m_hyperlinkVector.size() - j];
  323. tempLink.ex += charWidth;
  324. tempLink.sx += charWidth;
  325. }
  326.  
  327. isEnglish = false;
  328. }
  329. }
  330. else //[[[아랍어 모드]]]
  331. {
  332. // 아랍어이거나 아랍어 출력중 나오는 심볼이라면
  333. if (Arabic_IsInPresentation(wArabicChar) || Arabic_IsInSymbol(wArabicChar))
  334. {
  335. int charWidth = __DrawCharacter(pFontTexture, dataCodePage, Arabic_ConvSymbol(wArabicText[i]), dwColor);
  336. kHyperlink.ex += charWidth;
  337. x += charWidth;
  338.  
  339. //기존 추가한 하이퍼링크의 좌표 수정.
  340. for (int j = 1; j <= no_hyperlink; j++)
  341. {
  342. if(m_hyperlinkVector.size() < j)
  343. break;
  344.  
  345. SHyperlink & tempLink = m_hyperlinkVector[m_hyperlinkVector.size() - j];
  346. tempLink.ex += charWidth;
  347. tempLink.sx += charWidth;
  348. }
  349. }
  350. else //영어이거나, 영어 다음에 나오는 심볼이라면,
  351. {
  352. nEnglishBase = i;
  353. isEnglish = true;
  354. }
  355. }
  356. }
  357.  
  358. if (isEnglish)
  359. {
  360. for (int e = i + 1; e <= nEnglishBase;) {
  361. int ret = GetTextTag(&wArabicText[e], wArabicTextLen - e, len, hyperlinkBuffer);
  362.  
  363. if (ret == TEXT_TAG_PLAIN || ret == TEXT_TAG_TAG)
  364. {
  365. if (hyperlinkStep == 1)
  366. hyperlinkBuffer.append(1, wArabicText[e]);
  367. else
  368. {
  369. int charWidth = __DrawCharacter(pFontTexture, dataCodePage, wArabicText[e], dwColor);
  370. kHyperlink.ex += charWidth;
  371.  
  372. //기존 추가한 하이퍼링크의 좌표 수정.
  373. for (int j = 1; j <= no_hyperlink; j++)
  374. {
  375. if(m_hyperlinkVector.size() < j)
  376. break;
  377.  
  378. SHyperlink & tempLink = m_hyperlinkVector[m_hyperlinkVector.size() - j];
  379. tempLink.ex += charWidth;
  380. tempLink.sx += charWidth;
  381. }
  382. }
  383. }
  384. else
  385. {
  386. if (ret == TEXT_TAG_COLOR)
  387. dwColor = htoi(hyperlinkBuffer.c_str(), 8);
  388. else if (ret == TEXT_TAG_RESTORE_COLOR)
  389. dwColor = m_dwTextColor;
  390. else if (ret == TEXT_TAG_HYPERLINK_START)
  391. {
  392. hyperlinkStep = 1;
  393. hyperlinkBuffer = L"";
  394. }
  395. else if (ret == TEXT_TAG_HYPERLINK_END)
  396. {
  397. if (hyperlinkStep == 1)
  398. {
  399. ++hyperlinkStep;
  400. kHyperlink.ex = kHyperlink.sx = 0; // 실제 텍스트가 시작되는 위치
  401. }
  402. else
  403. {
  404. kHyperlink.text = hyperlinkBuffer;
  405. m_hyperlinkVector.push_back(kHyperlink);
  406. no_hyperlink++;
  407.  
  408. hyperlinkStep = 0;
  409. hyperlinkBuffer = L"";
  410. }
  411. }
  412. }
  413. e += len;
  414. }
  415.  
  416. }
  417. }
  418. else // 아랍외 다른 지역.
  419. {
  420. int x = 0;
  421. int len;
  422. int hyperlinkStep = 0;
  423. SHyperlink kHyperlink;
  424. std::wstring hyperlinkBuffer;
  425. SEmoji kEmoji;
  426. int emojiStep = 0;
  427. std::wstring emojiBuffer;
  428.  
  429. for (int i = 0; i < wTextLen; )
  430. {
  431. int ret = GetTextTag(&wText[i], wTextLen - i, len, hyperlinkBuffer);
  432.  
  433. if (ret == TEXT_TAG_PLAIN || ret == TEXT_TAG_TAG)
  434. {
  435. if (hyperlinkStep == 1)
  436. hyperlinkBuffer.append(1, wText[i]);
  437. else if (emojiStep == 1)
  438. emojiBuffer.append(1, wText[i]);
  439. else
  440. {
  441. int charWidth = __DrawCharacter(pFontTexture, dataCodePage, wText[i], dwColor);
  442. kHyperlink.ex += charWidth;
  443. x += charWidth;
  444. }
  445. }
  446. else
  447. {
  448. if (ret == TEXT_TAG_COLOR)
  449. dwColor = htoi(hyperlinkBuffer.c_str(), 8);
  450. else if (ret == TEXT_TAG_RESTORE_COLOR)
  451. dwColor = m_dwTextColor;
  452. else if (ret == TEXT_TAG_HYPERLINK_START)
  453. {
  454. hyperlinkStep = 1;
  455. hyperlinkBuffer = L"";
  456. }
  457. else if (ret == TEXT_TAG_HYPERLINK_END)
  458. {
  459. if (hyperlinkStep == 1)
  460. {
  461. ++hyperlinkStep;
  462. kHyperlink.ex = kHyperlink.sx = x; // 실제 텍스트가 시작되는 위치
  463. }
  464. else
  465. {
  466. kHyperlink.text = hyperlinkBuffer;
  467. m_hyperlinkVector.push_back(kHyperlink);
  468.  
  469. hyperlinkStep = 0;
  470. hyperlinkBuffer = L"";
  471. }
  472. }
  473. else if (ret == TEXT_TAG_EMOJI_START)
  474. {
  475. emojiStep = 1;
  476. emojiBuffer = L"";
  477. }
  478. else if (ret == TEXT_TAG_EMOJI_END)
  479. {
  480. kEmoji.x = x;
  481.  
  482. char retBuf[1024];
  483. int retLen = Ymir_WideCharToMultiByte(GetDefaultCodePage(), 0, emojiBuffer.c_str(), emojiBuffer.length(), retBuf, sizeof(retBuf) - 1, NULL, NULL);
  484. retBuf[retLen] = '\0';
  485.  
  486. char szPath[255];
  487. snprintf(szPath, sizeof(szPath), "icon/%s.tga", retBuf);
  488. if (CResourceManager::Instance().IsFileExist(szPath))
  489. {
  490. CGraphicImage * pImage = (CGraphicImage *)CResourceManager::Instance().GetResourcePointer(szPath);
  491. kEmoji.pInstance = CGraphicImageInstance::New();
  492. kEmoji.pInstance->SetImagePointer(pImage);
  493. m_emojiVector.push_back(kEmoji);
  494. memset(&kEmoji, 0, sizeof(SEmoji));
  495. for (int i = 0; i < pImage->GetWidth() / (pSpaceInfo->width-1); ++i)
  496. x += __DrawCharacter(pFontTexture, dataCodePage, ' ', dwColor);
  497. if (pImage->GetWidth() % (pSpaceInfo->width - 1) > 1)
  498. x += __DrawCharacter(pFontTexture, dataCodePage, ' ', dwColor);
  499. }
  500. emojiStep = 0;
  501. emojiBuffer = L"";
  502. }
  503. }
  504. i += len;
  505. }
  506. }
  507. }
  508.  
  509. if (token < end)
  510. {
  511. int newCodePage = ReadToken(token);
  512. dataCodePage = newCodePage; // 아랍 및 베트남 내부 데이터를 UTF8 을 사용하려 했으나 실패
  513. begin = token + 5;
  514. }
  515. else
  516. {
  517. begin = token;
  518. }
  519. }
  520.  
  521. pFontTexture->UpdateTexture();
  522.  
  523. m_isUpdate = true;
  524. }
  525.  
  526. void CGraphicTextInstance::Render(RECT * pClipRect)
  527. {
  528. if (!m_isUpdate)
  529. return;
  530.  
  531. CGraphicText* pkText=m_roText.GetPointer();
  532. if (!pkText)
  533. return;
  534.  
  535. CGraphicFontTexture* pFontTexture = pkText->GetFontTexturePointer();
  536. if (!pFontTexture)
  537. return;
  538.  
  539. float fStanX = m_v3Position.x;
  540. float fStanY = m_v3Position.y + 1.0f;
  541.  
  542. UINT defCodePage = GetDefaultCodePage();
  543.  
  544. if (defCodePage == CP_ARABIC)
  545. {
  546. switch (m_hAlign)
  547. {
  548. case HORIZONTAL_ALIGN_LEFT:
  549. fStanX -= m_textWidth;
  550. break;
  551.  
  552. case HORIZONTAL_ALIGN_CENTER:
  553. fStanX -= float(m_textWidth / 2);
  554. break;
  555. }
  556. }
  557. else
  558. {
  559. switch (m_hAlign)
  560. {
  561. case HORIZONTAL_ALIGN_RIGHT:
  562. fStanX -= m_textWidth;
  563. break;
  564.  
  565. case HORIZONTAL_ALIGN_CENTER:
  566. fStanX -= float(m_textWidth / 2);
  567. break;
  568. }
  569. }
  570.  
  571. switch (m_vAlign)
  572. {
  573. case VERTICAL_ALIGN_BOTTOM:
  574. fStanY -= m_textHeight;
  575. break;
  576.  
  577. case VERTICAL_ALIGN_CENTER:
  578. fStanY -= float(m_textHeight) / 2.0f;
  579. break;
  580. }
  581.  
  582. //WORD FillRectIndices[6] = { 0, 2, 1, 2, 3, 1 };
  583.  
  584. STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  585. STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  586. DWORD dwFogEnable = STATEMANAGER.GetRenderState(D3DRS_FOGENABLE);
  587. DWORD dwLighting = STATEMANAGER.GetRenderState(D3DRS_LIGHTING);
  588. STATEMANAGER.SetRenderState(D3DRS_FOGENABLE, FALSE);
  589. STATEMANAGER.SetRenderState(D3DRS_LIGHTING, FALSE);
  590.  
  591. STATEMANAGER.SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1);
  592. STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  593. STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  594. STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
  595. STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  596. STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
  597. STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
  598.  
  599. {
  600. const float fFontHalfWeight=1.0f;
  601.  
  602. float fCurX;
  603. float fCurY;
  604.  
  605. float fFontSx;
  606. float fFontSy;
  607. float fFontEx;
  608. float fFontEy;
  609. float fFontWidth;
  610. float fFontHeight;
  611. float fFontMaxHeight;
  612. float fFontAdvance;
  613.  
  614. SVertex akVertex[4];
  615. akVertex[0].z=m_v3Position.z;
  616. akVertex[1].z=m_v3Position.z;
  617. akVertex[2].z=m_v3Position.z;
  618. akVertex[3].z=m_v3Position.z;
  619.  
  620. CGraphicFontTexture::TCharacterInfomation* pCurCharInfo;
  621.  
  622. // 테두리
  623. if (m_isOutline)
  624. {
  625. fCurX=fStanX;
  626. fCurY=fStanY;
  627. fFontMaxHeight=0.0f;
  628.  
  629. CGraphicFontTexture::TPCharacterInfomationVector::iterator i;
  630. for (i=m_pCharInfoVector.begin(); i!=m_pCharInfoVector.end(); ++i)
  631. {
  632. pCurCharInfo = *i;
  633.  
  634. fFontWidth=float(pCurCharInfo->width);
  635. fFontHeight=float(pCurCharInfo->height);
  636. fFontAdvance=float(pCurCharInfo->advance);
  637.  
  638. // NOTE : 폰트 출력에 Width 제한을 둡니다. - [levites]
  639. if ((fCurX+fFontWidth)-m_v3Position.x > m_fLimitWidth)
  640. {
  641. if (m_isMultiLine)
  642. {
  643. fCurX=fStanX;
  644. fCurY+=fFontMaxHeight;
  645. }
  646. else
  647. {
  648. break;
  649. }
  650. }
  651.  
  652. if (pClipRect)
  653. {
  654. if (fCurY <= pClipRect->top)
  655. {
  656. fCurX += fFontAdvance;
  657. continue;
  658. }
  659. }
  660.  
  661. fFontSx = fCurX - 0.5f;
  662. fFontSy = fCurY - 0.5f;
  663. fFontEx = fFontSx + fFontWidth;
  664. fFontEy = fFontSy + fFontHeight;
  665.  
  666. pFontTexture->SelectTexture(pCurCharInfo->index);
  667. STATEMANAGER.SetTexture(0, pFontTexture->GetD3DTexture());
  668.  
  669. akVertex[0].u=pCurCharInfo->left;
  670. akVertex[0].v=pCurCharInfo->top;
  671. akVertex[1].u=pCurCharInfo->left;
  672. akVertex[1].v=pCurCharInfo->bottom;
  673. akVertex[2].u=pCurCharInfo->right;
  674. akVertex[2].v=pCurCharInfo->top;
  675. akVertex[3].u=pCurCharInfo->right;
  676. akVertex[3].v=pCurCharInfo->bottom;
  677.  
  678. akVertex[3].color = akVertex[2].color = akVertex[1].color = akVertex[0].color = m_dwOutLineColor;
  679.  
  680.  
  681. float feather = 0.0f; // m_fFontFeather
  682.  
  683. akVertex[0].y=fFontSy-feather;
  684. akVertex[1].y=fFontEy+feather;
  685. akVertex[2].y=fFontSy-feather;
  686. akVertex[3].y=fFontEy+feather;
  687.  
  688. // 왼
  689. akVertex[0].x=fFontSx-fFontHalfWeight-feather;
  690. akVertex[1].x=fFontSx-fFontHalfWeight-feather;
  691. akVertex[2].x=fFontEx-fFontHalfWeight+feather;
  692. akVertex[3].x=fFontEx-fFontHalfWeight+feather;
  693.  
  694. if (CGraphicBase::SetPDTStream((SPDTVertex*)akVertex, 4))
  695. STATEMANAGER.DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
  696.  
  697.  
  698. // 오른
  699. akVertex[0].x=fFontSx+fFontHalfWeight-feather;
  700. akVertex[1].x=fFontSx+fFontHalfWeight-feather;
  701. akVertex[2].x=fFontEx+fFontHalfWeight+feather;
  702. akVertex[3].x=fFontEx+fFontHalfWeight+feather;
  703.  
  704. if (CGraphicBase::SetPDTStream((SPDTVertex*)akVertex, 4))
  705. STATEMANAGER.DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
  706.  
  707. akVertex[0].x=fFontSx-feather;
  708. akVertex[1].x=fFontSx-feather;
  709. akVertex[2].x=fFontEx+feather;
  710. akVertex[3].x=fFontEx+feather;
  711.  
  712. // 위
  713. akVertex[0].y=fFontSy-fFontHalfWeight-feather;
  714. akVertex[1].y=fFontEy-fFontHalfWeight+feather;
  715. akVertex[2].y=fFontSy-fFontHalfWeight-feather;
  716. akVertex[3].y=fFontEy-fFontHalfWeight+feather;
  717.  
  718. // 20041216.myevan.DrawPrimitiveUP
  719. if (CGraphicBase::SetPDTStream((SPDTVertex*)akVertex, 4))
  720. STATEMANAGER.DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
  721.  
  722. // 아래
  723. akVertex[0].y=fFontSy+fFontHalfWeight-feather;
  724. akVertex[1].y=fFontEy+fFontHalfWeight+feather;
  725. akVertex[2].y=fFontSy+fFontHalfWeight-feather;
  726. akVertex[3].y=fFontEy+fFontHalfWeight+feather;
  727.  
  728. // 20041216.myevan.DrawPrimitiveUP
  729. if (CGraphicBase::SetPDTStream((SPDTVertex*)akVertex, 4))
  730. STATEMANAGER.DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
  731.  
  732. fCurX += fFontAdvance;
  733. }
  734. }
  735.  
  736. // 메인 폰트
  737. fCurX=fStanX;
  738. fCurY=fStanY;
  739. fFontMaxHeight=0.0f;
  740.  
  741. for (int i = 0; i < m_pCharInfoVector.size(); ++i)
  742. {
  743. pCurCharInfo = m_pCharInfoVector[i];
  744.  
  745. fFontWidth=float(pCurCharInfo->width);
  746. fFontHeight=float(pCurCharInfo->height);
  747. fFontMaxHeight=max(fFontHeight, pCurCharInfo->height);
  748. fFontAdvance=float(pCurCharInfo->advance);
  749.  
  750. // NOTE : 폰트 출력에 Width 제한을 둡니다. - [levites]
  751. if ((fCurX+fFontWidth)-m_v3Position.x > m_fLimitWidth)
  752. {
  753. if (m_isMultiLine)
  754. {
  755. fCurX=fStanX;
  756. fCurY+=fFontMaxHeight;
  757. }
  758. else
  759. {
  760. break;
  761. }
  762. }
  763.  
  764. if (pClipRect)
  765. {
  766. if (fCurY <= pClipRect->top)
  767. {
  768. fCurX += fFontAdvance;
  769. continue;
  770. }
  771. }
  772.  
  773. fFontSx = fCurX-0.5f;
  774. fFontSy = fCurY-0.5f;
  775. fFontEx = fFontSx + fFontWidth;
  776. fFontEy = fFontSy + fFontHeight;
  777.  
  778. pFontTexture->SelectTexture(pCurCharInfo->index);
  779. STATEMANAGER.SetTexture(0, pFontTexture->GetD3DTexture());
  780.  
  781. akVertex[0].x=fFontSx;
  782. akVertex[0].y=fFontSy;
  783. akVertex[0].u=pCurCharInfo->left;
  784. akVertex[0].v=pCurCharInfo->top;
  785.  
  786. akVertex[1].x=fFontSx;
  787. akVertex[1].y=fFontEy;
  788. akVertex[1].u=pCurCharInfo->left;
  789. akVertex[1].v=pCurCharInfo->bottom;
  790.  
  791. akVertex[2].x=fFontEx;
  792. akVertex[2].y=fFontSy;
  793. akVertex[2].u=pCurCharInfo->right;
  794. akVertex[2].v=pCurCharInfo->top;
  795.  
  796. akVertex[3].x=fFontEx;
  797. akVertex[3].y=fFontEy;
  798. akVertex[3].u=pCurCharInfo->right;
  799. akVertex[3].v=pCurCharInfo->bottom;
  800.  
  801. //m_dwColorInfoVector[i];
  802. //m_dwTextColor;
  803. akVertex[0].color = akVertex[1].color = akVertex[2].color = akVertex[3].color = m_dwColorInfoVector[i];
  804.  
  805. // 20041216.myevan.DrawPrimitiveUP
  806. if (CGraphicBase::SetPDTStream((SPDTVertex*)akVertex, 4))
  807. STATEMANAGER.DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
  808. //STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, akVertex, sizeof(SVertex));
  809.  
  810. fCurX += fFontAdvance;
  811. }
  812. }
  813.  
  814. if (m_isCursor)
  815. {
  816. // Draw Cursor
  817. float sx, sy, ex, ey;
  818. TDiffuse diffuse;
  819.  
  820. int curpos = CIME::GetCurPos();
  821. int compend = curpos + CIME::GetCompLen();
  822.  
  823. __GetTextPos(curpos, &sx, &sy);
  824.  
  825. // If Composition
  826. if(curpos<compend)
  827. {
  828. diffuse = 0x7fffffff;
  829. __GetTextPos(compend, &ex, &sy);
  830. }
  831. else
  832. {
  833. diffuse = 0xffffffff;
  834. ex = sx + 2;
  835. }
  836.  
  837. // FOR_ARABIC_ALIGN
  838. if (defCodePage == CP_ARABIC)
  839. {
  840. sx += m_v3Position.x - m_textWidth;
  841. ex += m_v3Position.x - m_textWidth;
  842. sy += m_v3Position.y;
  843. ey = sy + m_textHeight;
  844. }
  845. else
  846. {
  847. sx += m_v3Position.x;
  848. sy += m_v3Position.y;
  849. ex += m_v3Position.x;
  850. ey = sy + m_textHeight;
  851. }
  852.  
  853. switch (m_vAlign)
  854. {
  855. case VERTICAL_ALIGN_BOTTOM:
  856. sy -= m_textHeight;
  857. break;
  858.  
  859. case VERTICAL_ALIGN_CENTER:
  860. sy -= float(m_textHeight) / 2.0f;
  861. break;
  862. }
  863. // 최적화 사항
  864. // 같은텍스쳐를 사용한다면... STRIP을 구성하고, 텍스쳐가 변경되거나 끝나면 DrawPrimitive를 호출해
  865. // 최대한 숫자를 줄이도록하자!
  866.  
  867. TPDTVertex vertices[4];
  868. vertices[0].diffuse = diffuse;
  869. vertices[1].diffuse = diffuse;
  870. vertices[2].diffuse = diffuse;
  871. vertices[3].diffuse = diffuse;
  872. vertices[0].position = TPosition(sx, sy, 0.0f);
  873. vertices[1].position = TPosition(ex, sy, 0.0f);
  874. vertices[2].position = TPosition(sx, ey, 0.0f);
  875. vertices[3].position = TPosition(ex, ey, 0.0f);
  876.  
  877. STATEMANAGER.SetTexture(0, NULL);
  878.  
  879.  
  880. // 2004.11.18.myevan.DrawIndexPrimitiveUP -> DynamicVertexBuffer
  881. CGraphicBase::SetDefaultIndexBuffer(CGraphicBase::DEFAULT_IB_FILL_RECT);
  882. if (CGraphicBase::SetPDTStream(vertices, 4))
  883. STATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 4, 0, 2);
  884.  
  885. int ulbegin = CIME::GetULBegin();
  886. int ulend = CIME::GetULEnd();
  887.  
  888. if(ulbegin < ulend)
  889. {
  890. __GetTextPos(curpos+ulbegin, &sx, &sy);
  891. __GetTextPos(curpos+ulend, &ex, &sy);
  892.  
  893. sx += m_v3Position.x;
  894. sy += m_v3Position.y + m_textHeight;
  895. ex += m_v3Position.x;
  896. ey = sy + 2;
  897.  
  898. vertices[0].diffuse = 0xFFFF0000;
  899. vertices[1].diffuse = 0xFFFF0000;
  900. vertices[2].diffuse = 0xFFFF0000;
  901. vertices[3].diffuse = 0xFFFF0000;
  902. vertices[0].position = TPosition(sx, sy, 0.0f);
  903. vertices[1].position = TPosition(ex, sy, 0.0f);
  904. vertices[2].position = TPosition(sx, ey, 0.0f);
  905. vertices[3].position = TPosition(ex, ey, 0.0f);
  906.  
  907. STATEMANAGER.DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, c_FillRectIndices, D3DFMT_INDEX16, vertices, sizeof(TPDTVertex));
  908. }
  909. }
  910.  
  911. STATEMANAGER.RestoreRenderState(D3DRS_SRCBLEND);
  912. STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND);
  913.  
  914. STATEMANAGER.SetRenderState(D3DRS_FOGENABLE, dwFogEnable);
  915. STATEMANAGER.SetRenderState(D3DRS_LIGHTING, dwLighting);
  916.  
  917. //금강경 링크 띄워주는 부분.
  918. if (m_hyperlinkVector.size() != 0)
  919. {
  920. int lx = gs_mx - m_v3Position.x;
  921. int ly = gs_my - m_v3Position.y;
  922.  
  923. //아랍은 좌표 부호를 바꿔준다.
  924. if (GetDefaultCodePage() == CP_ARABIC) {
  925. lx = -lx;
  926. ly = -ly + m_textHeight;
  927. }
  928.  
  929. if (lx >= 0 && ly >= 0 && lx < m_textWidth && ly < m_textHeight)
  930. {
  931. std::vector<SHyperlink>::iterator it = m_hyperlinkVector.begin();
  932.  
  933. while (it != m_hyperlinkVector.end())
  934. {
  935. SHyperlink & link = *it++;
  936. if (lx >= link.sx && lx < link.ex)
  937. {
  938. gs_hyperlinkText = link.text;
  939. /*
  940. OutputDebugStringW(link.text.c_str());
  941. OutputDebugStringW(L"\n");
  942. */
  943. break;
  944. }
  945. }
  946. }
  947. }
  948. if (m_emojiVector.size() != 0)
  949. {
  950. for (std::vector<SEmoji>::iterator itor = m_emojiVector.begin(); itor != m_emojiVector.end(); ++itor)
  951. {
  952. SEmoji & rEmo = *itor;
  953. if (rEmo.pInstance)
  954. {
  955. rEmo.pInstance->SetPosition(fStanX + rEmo.x, (fStanY + 7.0) - (rEmo.pInstance->GetHeight() / 2));
  956. rEmo.pInstance->Render();
  957. }
  958. }
  959. }
  960. }
  961.  
  962. void CGraphicTextInstance::CreateSystem(UINT uCapacity)
  963. {
  964. ms_kPool.Create(uCapacity);
  965. }
  966.  
  967. void CGraphicTextInstance::DestroySystem()
  968. {
  969. ms_kPool.Destroy();
  970. }
  971.  
  972. CGraphicTextInstance* CGraphicTextInstance::New()
  973. {
  974. return ms_kPool.Alloc();
  975. }
  976.  
  977. void CGraphicTextInstance::Delete(CGraphicTextInstance* pkInst)
  978. {
  979. pkInst->Destroy();
  980. ms_kPool.Free(pkInst);
  981. }
  982.  
  983. void CGraphicTextInstance::ShowCursor()
  984. {
  985. m_isCursor = true;
  986. }
  987.  
  988. void CGraphicTextInstance::HideCursor()
  989. {
  990. m_isCursor = false;
  991. }
  992.  
  993. void CGraphicTextInstance::ShowOutLine()
  994. {
  995. m_isOutline = true;
  996. }
  997.  
  998. void CGraphicTextInstance::HideOutLine()
  999. {
  1000. m_isOutline = false;
  1001. }
  1002.  
  1003. void CGraphicTextInstance::SetColor(DWORD color)
  1004. {
  1005. if (m_dwTextColor != color)
  1006. {
  1007. for (int i = 0; i < m_pCharInfoVector.size(); ++i)
  1008. if (m_dwColorInfoVector[i] == m_dwTextColor)
  1009. m_dwColorInfoVector[i] = color;
  1010.  
  1011. m_dwTextColor = color;
  1012. }
  1013. }
  1014.  
  1015. void CGraphicTextInstance::SetColor(float r, float g, float b, float a)
  1016. {
  1017. SetColor(D3DXCOLOR(r, g, b, a));
  1018. }
  1019.  
  1020. void CGraphicTextInstance::SetOutLineColor(DWORD color)
  1021. {
  1022. m_dwOutLineColor=color;
  1023. }
  1024.  
  1025. void CGraphicTextInstance::SetOutLineColor(float r, float g, float b, float a)
  1026. {
  1027. m_dwOutLineColor=D3DXCOLOR(r, g, b, a);
  1028. }
  1029.  
  1030. void CGraphicTextInstance::SetSecret(bool Value)
  1031. {
  1032. m_isSecret = Value;
  1033. }
  1034.  
  1035. void CGraphicTextInstance::SetOutline(bool Value)
  1036. {
  1037. m_isOutline = Value;
  1038. }
  1039.  
  1040. void CGraphicTextInstance::SetFeather(bool Value)
  1041. {
  1042. if (Value)
  1043. {
  1044. m_fFontFeather = c_fFontFeather;
  1045. }
  1046. else
  1047. {
  1048. m_fFontFeather = 0.0f;
  1049. }
  1050. }
  1051.  
  1052. void CGraphicTextInstance::SetMultiLine(bool Value)
  1053. {
  1054. m_isMultiLine = Value;
  1055. }
  1056.  
  1057. void CGraphicTextInstance::SetHorizonalAlign(int hAlign)
  1058. {
  1059. m_hAlign = hAlign;
  1060. }
  1061.  
  1062. void CGraphicTextInstance::SetVerticalAlign(int vAlign)
  1063. {
  1064. m_vAlign = vAlign;
  1065. }
  1066.  
  1067. void CGraphicTextInstance::SetMax(int iMax)
  1068. {
  1069. m_iMax = iMax;
  1070. }
  1071.  
  1072. void CGraphicTextInstance::SetLimitWidth(float fWidth)
  1073. {
  1074. m_fLimitWidth = fWidth;
  1075. }
  1076.  
  1077. void CGraphicTextInstance::SetValueString(const std::string& c_stValue)
  1078. {
  1079. if (0 == m_stText.compare(c_stValue))
  1080. return;
  1081.  
  1082. m_stText = c_stValue;
  1083. m_isUpdate = false;
  1084. }
  1085.  
  1086. void CGraphicTextInstance::SetValue(const char* c_szText, size_t len)
  1087. {
  1088. if (0 == m_stText.compare(c_szText))
  1089. return;
  1090.  
  1091. m_stText = c_szText;
  1092. m_isUpdate = false;
  1093. }
  1094.  
  1095. void CGraphicTextInstance::SetPosition(float fx, float fy, float fz)
  1096. {
  1097. m_v3Position.x = fx;
  1098. m_v3Position.y = fy;
  1099. m_v3Position.z = fz;
  1100. }
  1101.  
  1102. void CGraphicTextInstance::SetTextPointer(CGraphicText* pText)
  1103. {
  1104. m_roText = pText;
  1105. }
  1106.  
  1107. const std::string & CGraphicTextInstance::GetValueStringReference()
  1108. {
  1109. return m_stText;
  1110. }
  1111.  
  1112. WORD CGraphicTextInstance::GetTextLineCount()
  1113. {
  1114. CGraphicFontTexture::TCharacterInfomation* pCurCharInfo;
  1115. CGraphicFontTexture::TPCharacterInfomationVector::iterator itor;
  1116.  
  1117. float fx = 0.0f;
  1118. WORD wLineCount = 1;
  1119. for (itor=m_pCharInfoVector.begin(); itor!=m_pCharInfoVector.end(); ++itor)
  1120. {
  1121. pCurCharInfo = *itor;
  1122.  
  1123. float fFontWidth=float(pCurCharInfo->width);
  1124. float fFontAdvance=float(pCurCharInfo->advance);
  1125. //float fFontHeight=float(pCurCharInfo->height);
  1126.  
  1127. // NOTE : 폰트 출력에 Width 제한을 둡니다. - [levites]
  1128. if (fx+fFontWidth > m_fLimitWidth)
  1129. {
  1130. fx = 0.0f;
  1131. ++wLineCount;
  1132. }
  1133.  
  1134. fx += fFontAdvance;
  1135. }
  1136.  
  1137. return wLineCount;
  1138. }
  1139.  
  1140. void CGraphicTextInstance::GetTextSize(int* pRetWidth, int* pRetHeight)
  1141. {
  1142. *pRetWidth = m_textWidth;
  1143. *pRetHeight = m_textHeight;
  1144. }
  1145.  
  1146. int CGraphicTextInstance::PixelPositionToCharacterPosition(int iPixelPosition)
  1147. {
  1148. int icurPosition = 0;
  1149. for (int i = 0; i < (int)m_pCharInfoVector.size(); ++i)
  1150. {
  1151. CGraphicFontTexture::TCharacterInfomation* pCurCharInfo = m_pCharInfoVector[i];
  1152. icurPosition += pCurCharInfo->width;
  1153.  
  1154. if (iPixelPosition < icurPosition)
  1155. return i;
  1156. }
  1157.  
  1158. return -1;
  1159. }
  1160.  
  1161. int CGraphicTextInstance::GetHorizontalAlign()
  1162. {
  1163. return m_hAlign;
  1164. }
  1165.  
  1166. void CGraphicTextInstance::__Initialize()
  1167. {
  1168. m_roText = NULL;
  1169.  
  1170. m_hAlign = HORIZONTAL_ALIGN_LEFT;
  1171. m_vAlign = VERTICAL_ALIGN_TOP;
  1172.  
  1173. m_iMax = 0;
  1174. m_fLimitWidth = 1600.0f; // NOTE : 해상도의 최대치. 이보다 길게 쓸 일이 있을까? - [levites]
  1175.  
  1176. m_isCursor = false;
  1177. m_isSecret = false;
  1178. m_isMultiLine = false;
  1179.  
  1180. m_isOutline = false;
  1181. m_fFontFeather = c_fFontFeather;
  1182.  
  1183. m_isUpdate = false;
  1184.  
  1185. m_textWidth = 0;
  1186. m_textHeight = 0;
  1187.  
  1188. m_v3Position.x = m_v3Position.y = m_v3Position.z = 0.0f;
  1189.  
  1190. m_dwOutLineColor=0xff000000;
  1191. }
  1192.  
  1193. void CGraphicTextInstance::Destroy()
  1194. {
  1195. m_stText="";
  1196. m_pCharInfoVector.clear();
  1197. m_dwColorInfoVector.clear();
  1198. m_hyperlinkVector.clear();
  1199.  
  1200. __Initialize();
  1201. if (m_emojiVector.size() != 0)
  1202. {
  1203. for (std::vector<SEmoji>::iterator itor = m_emojiVector.begin(); itor != m_emojiVector.end(); ++itor)
  1204. {
  1205. SEmoji & rEmo = *itor;
  1206. if (rEmo.pInstance)
  1207. {
  1208. CGraphicImageInstance::Delete(rEmo.pInstance);
  1209. rEmo.pInstance = NULL;
  1210. }
  1211. }
  1212. }
  1213. m_emojiVector.clear();
  1214. }
  1215.  
  1216. CGraphicTextInstance::CGraphicTextInstance()
  1217. {
  1218. __Initialize();
  1219. }
  1220.  
  1221. CGraphicTextInstance::~CGraphicTextInstance()
  1222. {
  1223. Destroy();
  1224. }
  1225.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement