1335 lines
37 KiB
C++
1335 lines
37 KiB
C++
#include "stdafx.h"
|
|
#include "KViewport.h"
|
|
#include "KTextRender.h"
|
|
#include "KPrimitiveSprite.h"
|
|
#include "KTextPhrase.h"
|
|
#include "KTextCacheManager.h"
|
|
#include "KTextEmoticonRender.h"
|
|
|
|
#include "KResourceManager.h"
|
|
#include <renderer/XFreeType.h>
|
|
#include <kfile/KFileManager.h>
|
|
#include <toolkit/nsl.h>
|
|
|
|
#include "shlobj.h"
|
|
|
|
#ifdef _COUNTRY_ME_
|
|
#include "KPangoCairo.h"
|
|
#endif
|
|
|
|
|
|
namespace
|
|
{
|
|
const int COLOR_VALUE = 1024;
|
|
};
|
|
|
|
|
|
XFreeType * KTextRender::s_pFreeType = new XFreeType;
|
|
K3DRenderDevice * KTextRender::m_pDevice = NULL;
|
|
KTextRender::FontMap KTextRender::m_mapFontInfo;
|
|
int KTextRender::m_nDefaultCodePage = CP_ACP; // AziaMafia DEFAUT UTF-8
|
|
HDC KTextRender::m_hDC;
|
|
bool bUseFreeType = false;
|
|
|
|
bool KTextRender::s_bIsOsVista = false;
|
|
std::string KTextRender::s_strLocale;
|
|
|
|
const char *KTextRender::KDEFAULT_FONT_NAME = "Default";
|
|
const char *KTextRender::KDEFAULT_FONT_NAME2 = "font_default"; /// 2010.11.05 - prodongi
|
|
const char *KTextRender::KDEFAULT_FONT_01 = "font_01";
|
|
const char *KTextRender::KDEFAULT_FONT_02 = "font_02";
|
|
const char *KTextRender::KDEFAULT_FONT_03 = "font_03"; // 2010.08.26 - prodongi
|
|
|
|
const int KTextRender::KDEFAULT_FONT_SIZE = 9;
|
|
KTextRender::StringTableHandler* KTextRender::s_pStringTableHandler;
|
|
float KTextRender::m_fFreeTypeSizeRatio = 1.0f;
|
|
bool KTextRender::m_bIncreaseEnglishFontSize= false;
|
|
int KTextRender::m_nFreeTypeYOffset = 0;
|
|
|
|
unsigned char KTextRender::s_randColor[1024];
|
|
int KTextRender::s_nColorValue = 0;
|
|
|
|
#ifdef _COUNTRY_ME_
|
|
KFontManager KTextRender::s_fontManager;
|
|
#endif
|
|
|
|
void KTextRender::GenerateRandColor()
|
|
{
|
|
for( int i(0); COLOR_VALUE>i; i++ )
|
|
{
|
|
s_randColor[i] = rand()%255;
|
|
}
|
|
}
|
|
|
|
unsigned char KTextRender::GetNextRandColor()
|
|
{
|
|
if( s_nColorValue > COLOR_VALUE )
|
|
s_nColorValue = 0;
|
|
|
|
return s_randColor[s_nColorValue++];
|
|
}
|
|
|
|
static int incSizeIfNoMultiByte( const char *str, int nFontSize )
|
|
{
|
|
const unsigned char *p = (const unsigned char *)str;
|
|
while( *p )
|
|
{
|
|
if( *p & 0x80 ) return nFontSize;
|
|
++p;
|
|
}
|
|
|
|
return nFontSize+2;
|
|
}
|
|
|
|
KTextRender::FREETYPE_TEXT_FONT_INFO::FREETYPE_TEXT_FONT_INFO( const char *szAlias, const char *szFontFileName,bool *returnSuccess )
|
|
{
|
|
pFontStream = NULL;
|
|
|
|
if(returnSuccess)
|
|
*returnSuccess = true;
|
|
|
|
//pFontStream = NULL;
|
|
bIsFreeType = true;
|
|
KStream *pFontResource = KFileManager::Instance().CreateStreamFromResource( szFontFileName );
|
|
if( !pFontResource )
|
|
{
|
|
TCHAR szFontPath[_MAX_PATH];
|
|
|
|
|
|
if( SHGetFolderPath( NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, szFontPath ) == E_FAIL )
|
|
{
|
|
assert(0 && "FREETYPE_TEXT_FONT_INFO - resource not found!!" );
|
|
*returnSuccess = false;
|
|
}
|
|
else
|
|
{
|
|
std::string path = szFontPath;
|
|
path += "\\";
|
|
path += szFontFileName;
|
|
|
|
FILE *fp = fopen(path.c_str(),"rb");
|
|
if(fp)
|
|
{
|
|
fseek( fp, 0, SEEK_END );
|
|
size_t fsize = ftell( fp );
|
|
fseek( fp, 0, SEEK_SET );
|
|
|
|
pFontStream = new char[fsize];
|
|
fread( pFontStream, sizeof(char)*fsize, 1, fp );
|
|
|
|
if( !s_pFreeType->IsInitialized() ) s_pFreeType->Init();
|
|
if( !s_pFreeType->LoadFont( szAlias, pFontStream, fsize ) )
|
|
{
|
|
assert(0 && "FREETYPE_TEXT_FONT_INFO - LoadFont Failed!!" );
|
|
delete [] pFontStream;
|
|
if(returnSuccess)
|
|
*returnSuccess = false;
|
|
}
|
|
|
|
KFileManager::Instance().DeleteStream( pFontResource );
|
|
|
|
fclose( fp );
|
|
}
|
|
else
|
|
{
|
|
assert(0 && "FREETYPE_TEXT_FONT_INFO - resource not found!!" );
|
|
*returnSuccess = false;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pFontStream = new char[ pFontResource->GetLength() ];
|
|
pFontResource->Read( pFontStream, pFontResource->GetLength() );
|
|
if( !s_pFreeType->IsInitialized() ) s_pFreeType->Init();
|
|
if( !s_pFreeType->LoadFont( szAlias, pFontStream, pFontResource->GetLength() ) )
|
|
{
|
|
assert(0 && "FREETYPE_TEXT_FONT_INFO - LoadFont Failed!!" );
|
|
delete [] pFontStream;
|
|
if(returnSuccess)
|
|
*returnSuccess = false;
|
|
}
|
|
|
|
KFileManager::Instance().DeleteStream( pFontResource );
|
|
}
|
|
}
|
|
|
|
#ifndef _COUNTRY_ME_
|
|
|
|
/// 2011.02.23 isSpriteScroll 추가 - prodongi
|
|
KTextRender::KTextRender(LPCSTR lpszText, KColor color, LPCSTR lpszFontName, int nSize,
|
|
DWORD & dwWidth, DWORD & dwHeight, DWORD dwAlign, DWORD dwFlag, bool bStaticSize, KColor color_fx, float fZPos/*0.0f*/, bool bRandomColor/*=false*/, bool bUseEmoticonFilter, bool isSpriteScroll )
|
|
:m_dwWidth(dwWidth), m_dwHeight(dwHeight), m_pEmoticonLayerRender(NULL), m_prSprite(NULL)
|
|
{
|
|
//assert( _CrtCheckMemory() );
|
|
//if( _CrtCheckMemory() == 0 )
|
|
// SDEBUGLOG("_CrtCheckMemory - KTextRender::KTextRender");
|
|
// SDEBUGLOG("KTextRender::GetStringSize - text[%s], font[%s]", lpszText, lpszFontName);
|
|
|
|
int bufferImgWidth = 0; /// 2011.02.23 Text Image의 사이즈- prodongi
|
|
int bufferImgHeight = 0;
|
|
|
|
DWORD dwTextColor = DWORD((color.a << 24) | (color.r << 16) | (color.g << 8) | (color.b));
|
|
|
|
TEXT_FONT_INFO * pFontInfo = _FindFont(lpszFontName, nSize);
|
|
|
|
if( pFontInfo && pFontInfo->bIsFreeType && m_bIncreaseEnglishFontSize ) nSize = incSizeIfNoMultiByte( lpszText, nSize );
|
|
|
|
// InitTextRender가 불려지지 않았으므로
|
|
if(!m_pDevice)
|
|
{
|
|
assert(false && "please call InitTextRender");
|
|
}
|
|
|
|
|
|
m_prSprite = new KSpritePrimitive(false); // [MEMORY_LEAK] 2012. 3. 2 - marine 메모리 해제해줌..
|
|
m_spResSprite = new KResSprite; // [MEMORY_LEAK] 2012. 3. 2 - marine 메모리 해제해줌..
|
|
|
|
std::string strText = lpszText;
|
|
for( size_t i = 0; i < strText.size(); ++i )
|
|
{
|
|
//if( strText[i] == 0x1D ) strText[i] = '&';
|
|
if( strText[i] == 0x1E ) strText[i] = '<';
|
|
if( strText[i] == 0x1F ) strText[i] = '>';
|
|
}
|
|
|
|
// emoticon
|
|
bool bExistEmoticon = false;
|
|
DWORD dwOldHeight = dwHeight;
|
|
if( bUseEmoticonFilter )
|
|
CheckEmoticon( strText, lpszFontName, nSize, dwFlag, dwWidth, dwHeight, bStaticSize, fZPos );
|
|
if( dwOldHeight != dwHeight ) bExistEmoticon = true;
|
|
|
|
m_spTexture = KTextCacheManager::GetInstance()->FindCache( strText.c_str(), color, lpszFontName, nSize, dwWidth, dwHeight, dwFlag, color_fx);
|
|
|
|
if(m_spTexture != NULL)
|
|
{
|
|
if (isSpriteScroll) /// 2011.03.22 - prodongi
|
|
{
|
|
m_spResSprite->SetTexture(m_spTexture, m_spTexture->GetTextOriImgRect());
|
|
m_prSprite->SetRes(m_spResSprite);
|
|
m_prSprite->setScrollImgUv(m_spTexture->GetTextOriImgWidth(), m_spTexture->GetTextOriImgHeight());
|
|
}
|
|
else
|
|
{
|
|
m_spResSprite->SetTexture(m_spTexture, NULL);
|
|
m_prSprite->SetRes(m_spResSprite);
|
|
}
|
|
return;
|
|
}
|
|
|
|
KRect rcTexRect;
|
|
|
|
if( pFontInfo == NULL || !pFontInfo->bIsFreeType )
|
|
{
|
|
BYTE *pBitmapBuffer = NULL;
|
|
|
|
BITMAPINFO bmi;
|
|
ZeroMemory( &bmi.bmiHeader, sizeof(bmi.bmiHeader) );
|
|
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
|
|
bmi.bmiHeader.biWidth = dwWidth;
|
|
bmi.bmiHeader.biHeight = -int(dwHeight);
|
|
bmi.bmiHeader.biPlanes = 1;
|
|
bmi.bmiHeader.biCompression = BI_RGB;
|
|
//bmi.bmiHeader.biBitCount = 16;
|
|
bmi.bmiHeader.biBitCount = 32;
|
|
|
|
HBITMAP hBmBitmap = CreateDIBSection( m_hDC, &bmi, DIB_RGB_COLORS, (VOID**)&pBitmapBuffer, NULL, 0 );
|
|
//DWORD dwStride = dwWidth * 2;
|
|
DWORD dwStride = dwWidth * 4;
|
|
if ( dwStride % 4 )
|
|
dwStride = ((dwStride / 4) + 1) * 4;
|
|
|
|
ZeroMemory( pBitmapBuffer, dwStride * dwHeight );
|
|
|
|
WIN32_TEXT_FONT_INFO * pInfo = (WIN32_TEXT_FONT_INFO *)_FindFont(lpszFontName, nSize);
|
|
|
|
if(!pInfo)
|
|
{
|
|
if( strlen(lpszFontName) > 0 )
|
|
{
|
|
KTextRender::AddFont(lpszFontName,nSize);
|
|
pInfo = (WIN32_TEXT_FONT_INFO *)_FindFont(lpszFontName, nSize);
|
|
}
|
|
else
|
|
{
|
|
pInfo = (WIN32_TEXT_FONT_INFO *)_FindFont("default", nSize);
|
|
}
|
|
}
|
|
|
|
HBITMAP hBitmapOld = reinterpret_cast<HBITMAP>( ::SelectObject(m_hDC, hBmBitmap));
|
|
|
|
HFONT hFontOld;
|
|
|
|
// Font Flag Setting
|
|
if(dwFlag & KTFLAG_BOLD)
|
|
{
|
|
hFontOld = reinterpret_cast<HFONT>(::SelectObject(m_hDC,pInfo->hBoldFont ) );
|
|
}
|
|
else if(dwFlag & KTFLAG_UNDER)
|
|
{
|
|
hFontOld = reinterpret_cast<HFONT>(::SelectObject(m_hDC,pInfo->hUnderLineFont ) );
|
|
}
|
|
else if(dwFlag & KTFLAG_STRIKE)
|
|
{
|
|
hFontOld = reinterpret_cast<HFONT>(::SelectObject(m_hDC,pInfo->hStrikeOutFont ) );
|
|
}
|
|
else
|
|
{
|
|
hFontOld = reinterpret_cast<HFONT>(::SelectObject(m_hDC, pInfo->hDefaultFont) );
|
|
}
|
|
|
|
SetTextAlign(m_hDC, TA_TOP );
|
|
|
|
DWORD dwColor = RGB(255,255,255);
|
|
|
|
if(dwFlag & KTFLAG_INVERSE)
|
|
{
|
|
SetBkMode( m_hDC, TRANSPARENT );
|
|
SetBkColor( m_hDC, 0x00000000 );
|
|
SetTextColor( m_hDC, dwColor );
|
|
}
|
|
|
|
else
|
|
{
|
|
SetBkMode( m_hDC, TRANSPARENT );
|
|
SetBkColor( m_hDC, 0x00000000 );
|
|
SetTextColor( m_hDC, dwColor );
|
|
}
|
|
|
|
unsigned int i;
|
|
for(i = 2; i < dwWidth+4;)
|
|
i *= 2;
|
|
|
|
DWORD dwTexWidth = i;
|
|
|
|
for(i = 2; i < dwHeight+4;)
|
|
i *= 2;
|
|
|
|
DWORD dwTexHeight = i;
|
|
|
|
RECT rcRect;
|
|
|
|
rcRect.left = 0; rcRect.top = 0; rcRect.right = dwWidth; rcRect.bottom = dwHeight;
|
|
rcTexRect.left = 0; rcTexRect.top = 0; rcTexRect.right = dwWidth; rcTexRect.bottom = dwHeight;
|
|
|
|
// MIMI
|
|
if( bExistEmoticon )
|
|
{
|
|
// 전체 height 의 절반에서 폰트 height 의 절반을 뺀것이 top
|
|
rcRect.top = dwHeight/2 - dwOldHeight/2;
|
|
rcRect.top += 2;
|
|
}
|
|
|
|
::DrawText(m_hDC,
|
|
strText.c_str(),
|
|
static_cast<int>(strText.size()),
|
|
&rcRect,
|
|
dwAlign | DT_NOPREFIX
|
|
#ifdef _COUTNRY_ME_ // sonador #2.4.10.2
|
|
| DT_RTLREADING
|
|
#endif
|
|
);
|
|
|
|
m_spTexture = m_pDevice->CreateTexture(dwTexWidth,dwTexHeight, K3DFMT_A8R8G8B8 );
|
|
|
|
if(m_spTexture == NULL)
|
|
return;
|
|
|
|
int nStride;
|
|
DWORD* pImgBuf32;
|
|
|
|
m_spTexture->LockRect(&rcTexRect, reinterpret_cast<void **>(&pImgBuf32),nStride);
|
|
assert(pImgBuf32 && "m_spTexture->LockRect(&rcTexRect, reinterpret_cast<void **>(&pImgBuf32),nStride);");
|
|
if( NULL == pImgBuf32 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
nStride /= sizeof(DWORD);
|
|
|
|
int textoffset = 0;
|
|
if ( dwFlag & KTFLAG_GLOW )
|
|
{
|
|
textoffset = 2;
|
|
//unsigned short wGlowColor = unsigned short((0x6 << 12) | (0xa << 8) | (0xa << 4) | 0xa);
|
|
DWORD dwGlowColor = DWORD((0x60 << 24) | (0xa0 << 16) | (0xa0 << 8) | 0xa0);
|
|
|
|
//for(i = 0; i < dwHeight; ++i)
|
|
//{
|
|
// WORD *pImg = (WORD*)&pBitmapBuffer[i*dwStride];
|
|
// for(unsigned int j = 0; j < dwWidth; ++j)
|
|
// {
|
|
// if( *pImg++ )
|
|
// {
|
|
// *(pImgBuf16 + (i+0) * nStride + (j+0)) = wGlowColor;
|
|
// *(pImgBuf16 + (i+0) * nStride + (j+1)) = wGlowColor;
|
|
// *(pImgBuf16 + (i+0) * nStride + (j+2)) = wGlowColor;
|
|
// *(pImgBuf16 + (i+0) * nStride + (j+3)) = wGlowColor;
|
|
// *(pImgBuf16 + (i+0) * nStride + (j+4)) = wGlowColor;
|
|
|
|
// *(pImgBuf16 + (i+1) * nStride + (j+0)) = wGlowColor;
|
|
// *(pImgBuf16 + (i+2) * nStride + (j+0)) = wGlowColor;
|
|
// *(pImgBuf16 + (i+3) * nStride + (j+0)) = wGlowColor;
|
|
// *(pImgBuf16 + (i+4) * nStride + (j+0)) = wGlowColor;
|
|
// *(pImgBuf16 + (i+1) * nStride + (j+4)) = wGlowColor;
|
|
// *(pImgBuf16 + (i+2) * nStride + (j+4)) = wGlowColor;
|
|
// *(pImgBuf16 + (i+3) * nStride + (j+4)) = wGlowColor;
|
|
// *(pImgBuf16 + (i+4) * nStride + (j+4)) = wGlowColor;
|
|
|
|
// *(pImgBuf16 + (i+4) * nStride + (j+1)) = wGlowColor;
|
|
// *(pImgBuf16 + (i+4) * nStride + (j+2)) = wGlowColor;
|
|
// *(pImgBuf16 + (i+4) * nStride + (j+3)) = wGlowColor;
|
|
// }
|
|
// }
|
|
//}
|
|
|
|
for(i = 0; i < dwHeight; ++i)
|
|
{
|
|
DWORD *pImg = (DWORD*) &pBitmapBuffer[i*dwStride];
|
|
for(unsigned int j = 0; j < dwWidth; ++j)
|
|
{
|
|
if( *pImg++ )
|
|
{
|
|
*(pImgBuf32 + (i+0) * nStride + (j+0)) = dwGlowColor;
|
|
if( j != dwWidth - 1 ) *(pImgBuf32 + (i+0) * nStride + (j+1)) = dwGlowColor;
|
|
if( j != dwWidth - 1 ) *(pImgBuf32 + (i+0) * nStride + (j+2)) = dwGlowColor;
|
|
if( j != dwWidth - 1 ) *(pImgBuf32 + (i+0) * nStride + (j+3)) = dwGlowColor;
|
|
if( j != dwWidth - 1 ) *(pImgBuf32 + (i+0) * nStride + (j+4)) = dwGlowColor;
|
|
|
|
if( i != dwHeight - 1 )
|
|
{
|
|
*(pImgBuf32 + (i+1) * nStride + (j+0)) = dwGlowColor;
|
|
*(pImgBuf32 + (i+2) * nStride + (j+0)) = dwGlowColor;
|
|
*(pImgBuf32 + (i+3) * nStride + (j+0)) = dwGlowColor;
|
|
*(pImgBuf32 + (i+4) * nStride + (j+0)) = dwGlowColor;
|
|
if( j != dwWidth - 1 ) *(pImgBuf32 + (i+1) * nStride + (j+4)) = dwGlowColor;
|
|
if( j != dwWidth - 1 ) *(pImgBuf32 + (i+2) * nStride + (j+4)) = dwGlowColor;
|
|
if( j != dwWidth - 1 ) *(pImgBuf32 + (i+3) * nStride + (j+4)) = dwGlowColor;
|
|
if( j != dwWidth - 1 ) *(pImgBuf32 + (i+4) * nStride + (j+4)) = dwGlowColor;
|
|
|
|
if( j != dwWidth - 1 ) *(pImgBuf32 + (i+4) * nStride + (j+1)) = dwGlowColor;
|
|
if( j != dwWidth - 1 ) *(pImgBuf32 + (i+4) * nStride + (j+2)) = dwGlowColor;
|
|
if( j != dwWidth - 1 ) *(pImgBuf32 + (i+4) * nStride + (j+3)) = dwGlowColor;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ( dwFlag & KTFLAG_GLOW || dwFlag & KTFLAG_OUTLINE )
|
|
{
|
|
int so = 2;
|
|
if ( !(dwFlag & KTFLAG_GLOW) )
|
|
{
|
|
textoffset = 1;
|
|
so = 1;
|
|
}
|
|
|
|
//unsigned short wShadowColor = unsigned short((0xf << 12) | (0x4 << 8) | (0x4 << 4) | 0x4);
|
|
//for(i = 0; i < dwHeight; ++i)
|
|
//{
|
|
// WORD *pImg = (WORD*)&pBitmapBuffer[i*dwStride];
|
|
// for(unsigned int j = 0; j < dwWidth; ++j)
|
|
// {
|
|
// if( *pImg++ )
|
|
// {
|
|
// *(pImgBuf16 + (i+so-1) * nStride + (j+so-1)) = wShadowColor;
|
|
// *(pImgBuf16 + (i+so-1) * nStride + (j+so)) = wShadowColor;
|
|
// *(pImgBuf16 + (i+so-1) * nStride + (j+so+1)) = wShadowColor;
|
|
// *(pImgBuf16 + (i+so) * nStride + (j+so-1)) = wShadowColor;
|
|
// *(pImgBuf16 + (i+so) * nStride + (j+so+1)) = wShadowColor;
|
|
// *(pImgBuf16 + (i+so+1) * nStride + (j+so-1)) = wShadowColor;
|
|
// *(pImgBuf16 + (i+so+1) * nStride + (j+so)) = wShadowColor;
|
|
// *(pImgBuf16 + (i+so+1) * nStride + (j+so+1)) = wShadowColor;
|
|
// }
|
|
// }
|
|
//}
|
|
|
|
DWORD dwShadowColor = DWORD((0xf0 << 24) | (0x40 << 16) | (0x40 << 8) | 0x40);
|
|
for(i = 0; i < dwHeight; ++i)
|
|
{
|
|
DWORD *pImg = (DWORD*)&pBitmapBuffer[i*dwStride];
|
|
for(unsigned int j = 0; j < dwWidth; ++j)
|
|
{
|
|
if( *pImg++ )
|
|
{
|
|
if( i + so - 1 < dwHeight )
|
|
{
|
|
if( j + so - 1 < dwWidth ) *(pImgBuf32 + (i+so-1) * nStride + (j+so-1)) = dwShadowColor;
|
|
if( j + so < dwWidth ) *(pImgBuf32 + (i+so-1) * nStride + (j+so)) = dwShadowColor;
|
|
if( j + so + 1 < dwWidth ) *(pImgBuf32 + (i+so-1) * nStride + (j+so+1)) = dwShadowColor;
|
|
}
|
|
|
|
if( i + so < dwHeight )
|
|
{
|
|
if( j + so - 1 < dwWidth ) *(pImgBuf32 + (i+so) * nStride + (j+so-1)) = dwShadowColor;
|
|
if( j + so + 1 < dwWidth ) *(pImgBuf32 + (i+so) * nStride + (j+so+1)) = dwShadowColor;
|
|
}
|
|
|
|
if( i + so + 1 < dwHeight )
|
|
{
|
|
if( j + so - 1 < dwWidth ) *(pImgBuf32 + (i+so+1) * nStride + (j+so-1)) = dwShadowColor;
|
|
if( j + so < dwWidth ) *(pImgBuf32 + (i+so+1) * nStride + (j+so)) = dwShadowColor;
|
|
if( j + so + 1 < dwWidth ) *(pImgBuf32 + (i+so+1) * nStride + (j+so+1)) = dwShadowColor;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( dwFlag & KTFLAG_SHADOW )
|
|
{
|
|
//unsigned short wShadowColor = unsigned short((0xf << 12) | (0x4 << 8) | (0x4 << 4) | 0x4);
|
|
//for(i = 0; i < dwHeight; ++i)
|
|
//{
|
|
// WORD *pImg = (WORD*)&pBitmapBuffer[i*dwStride];
|
|
// for(unsigned int j = 0; j < dwWidth; ++j)
|
|
// {
|
|
// if( *pImg++ )
|
|
// *(pImgBuf16 + (i+1) * nStride + (j+1)) = wShadowColor;
|
|
// }
|
|
//}
|
|
|
|
DWORD dwShadowColor = DWORD((0xff << 24) | (0x40 << 16) | (0x40 << 8) | 0x40);
|
|
for(i = 0; i < dwHeight; ++i)
|
|
{
|
|
DWORD *pImg = (DWORD*)&pBitmapBuffer[i*dwStride];
|
|
for(unsigned int j = 0; j < dwWidth; ++j)
|
|
{
|
|
if( *pImg++ )
|
|
{
|
|
if( i != dwHeight - 1 && j != dwWidth - 1 )
|
|
*(pImgBuf32 + (i+1) * nStride + (j+1)) = dwShadowColor;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//unsigned short wTextColor = unsigned short((0xf << 12) | ((color.b>>4) << 8) | ((color.g>>4) << 4) | (color.r>>4));
|
|
//for(i = 0; i < dwHeight; ++i)
|
|
//{
|
|
// WORD *pImg = (WORD*)&pBitmapBuffer[i*dwStride];
|
|
// for(unsigned int j = 0; j < dwWidth; ++j)
|
|
// {
|
|
// if( *pImg++ )
|
|
// *(pImgBuf16 + (i+textoffset) * nStride + (j+textoffset)) = wTextColor;
|
|
// }
|
|
//}
|
|
|
|
for(i = 0; i < dwHeight; ++i)
|
|
{
|
|
DWORD *pImg = (DWORD*)&pBitmapBuffer[i*dwStride];
|
|
for(unsigned int j = 0; j < dwWidth; ++j)
|
|
{
|
|
if( *pImg++ )
|
|
{
|
|
if( i + textoffset < dwHeight && j + textoffset < dwWidth )
|
|
{
|
|
if( bRandomColor )
|
|
{
|
|
dwTextColor = DWORD((0xFF << 24) | (GetNextRandColor() << 16) | (GetNextRandColor() << 8) | (GetNextRandColor()));
|
|
}
|
|
|
|
*(pImgBuf32 + (i+textoffset) * nStride + (j+textoffset)) = dwTextColor;
|
|
}
|
|
}
|
|
else if( dwFlag & KTFLAG_INVERSE )
|
|
{
|
|
if( i + textoffset + 3 < dwHeight && j + textoffset < dwWidth )
|
|
{
|
|
*(pImgBuf32 + (i+textoffset) * nStride + (j+textoffset)) = 0xFFCDCDCD;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_spTexture->Unlock();
|
|
|
|
SelectObject(m_hDC, hFontOld);
|
|
SelectObject(m_hDC, hBitmapOld);
|
|
DeleteObject(hBmBitmap);
|
|
}
|
|
else
|
|
{
|
|
//SDEBUGLOG("KTextRender::KTextRender s_pFreeType->Draw - begin");
|
|
//SDEBUGLOG("\tKTextRender::KTextRender - text[%s], font[%s], %p", lpszText, lpszFontName, s_pFreeType);
|
|
//SDEBUGLOG("\tKTextRender::KTextRender - %s, %s, %d, %d", strText.c_str(), lpszFontName, strText.size(), m_nDefaultCodePage);
|
|
/*if( _CrtCheckMemory() == 0 )
|
|
SDEBUGLOG("_CrtCheckMemory - KTextRender::KTextRender s_pFreeType->Draw - begin");*/
|
|
// assert( _CrtCheckMemory() );
|
|
|
|
rcTexRect.left = 0; rcTexRect.top = 0; rcTexRect.right = dwWidth; rcTexRect.bottom = dwHeight;
|
|
|
|
wchar_t *pBuffer = new wchar_t[ strText.size()+1 ];
|
|
// assert( _CrtCheckMemory() );
|
|
int len = ::MultiByteToWideChar( m_nDefaultCodePage, 0, strText.c_str(), strText.size(), pBuffer, strText.size() );
|
|
// assert( _CrtCheckMemory() );
|
|
pBuffer[len] = 0;
|
|
// assert( _CrtCheckMemory() );
|
|
s_pFreeType->SetFontColor( color.b, color.g, color.r ); //순서에 문제가 n있음.
|
|
s_pFreeType->SetEffectColor( color_fx.b, color_fx.g, color_fx.r );//순서에 문제가 있음.
|
|
int nWidth, nHeight;
|
|
|
|
// 폰트 이펙트 불일치는 일단 이렇게 땜빵. -_-
|
|
int nFlag = 0;/*XFreeType::FT_SHADOW*/;
|
|
if( dwFlag & KTFLAG_SHADOW ) nFlag = XFreeType::FT_SHADOW_LV1;
|
|
if( dwFlag & KTFLAG_GLOW ) nFlag = XFreeType::FT_STROKE_LV2;
|
|
if( dwFlag & KTFLAG_GLOW2X ) nFlag = XFreeType::FT_STROKE_LV3;
|
|
|
|
// 2010. 8. 20 - marine <out><b>태그가 적용되지 않아서 추가
|
|
if( dwFlag & KTFLAG_OUTLINE) nFlag = XFreeType::FT_OUTLINE;
|
|
if( dwFlag & KTFLAG_BOLD) nFlag = XFreeType::FT_BOLD;
|
|
|
|
|
|
/*if( _CrtCheckMemory() == 0 )
|
|
SDEBUGLOG("_CrtCheckMemory - KTextRender::KTextRender s_pFreeType->Draw - 2");*/
|
|
|
|
// assert( _CrtCheckMemory() );
|
|
|
|
//SDEBUGLOG("\tKTextRender::KTextRender - text[%s], font[%s], %p, text_w[%ws]", lpszText, lpszFontName, s_pFreeType,pBuffer);
|
|
//SDEBUGLOG("\tKTextRender::KTextRender - %s, %s, %d, %d", strText.c_str(), lpszFontName, len, m_nDefaultCodePage);
|
|
//
|
|
/*
|
|
LPCSTR lpszText, KColor color, LPCSTR lpszFontName, int nSize,
|
|
DWORD & dwWidth, DWORD & dwHeight, DWORD dwAlign, DWORD dwFlag, bool bS
|
|
*/
|
|
// assert( _CrtCheckMemory() );
|
|
const XAlphaImage *pImg = s_pFreeType->Draw( lpszFontName, pBuffer, &nWidth, &nHeight, nSize*m_fFreeTypeSizeRatio, nFlag, m_nFreeTypeYOffset, dwFlag & KTFLAG_UNDER, dwFlag & KTFLAG_INVERSE, false, pFontInfo->bHinting );
|
|
//SDEBUGLOG("KTextRender::KTextRender s_pFreeType->Draw - end");
|
|
delete [] pBuffer;
|
|
|
|
if( pImg == NULL ) return;
|
|
|
|
DWORD dwTexWidth = pImg->GetWidth(), dwTexHeight = pImg->GetHeight();
|
|
|
|
if (isSpriteScroll) /// 2011.02.23 - prodongi
|
|
{
|
|
dwTexWidth = dwWidth;
|
|
bufferImgWidth = pImg->GetWidth();
|
|
bufferImgHeight = pImg->GetHeight();
|
|
}
|
|
|
|
int nExpX, nExpY;
|
|
K3DRenderDevice::GetSquareSize( dwTexWidth,dwTexHeight, nExpX, nExpY );
|
|
m_spTexture = m_pDevice->CreateTexture(nExpX, nExpY, K3DFMT_A8R8G8B8 );
|
|
|
|
if(m_spTexture == NULL)
|
|
return;
|
|
|
|
int nStride;
|
|
//WORD * pImgBuf16 = NULL;
|
|
char * pImgBuf32 = NULL;
|
|
|
|
rcTexRect.left = 0; rcTexRect.top = 0; rcTexRect.right = dwTexWidth; rcTexRect.bottom = dwTexHeight;
|
|
|
|
m_spTexture->LockRect(&rcTexRect, reinterpret_cast<void **>(&pImgBuf32),nStride);
|
|
assert( pImgBuf32 && "m_spTexture->LockRect(&rcTexRect, reinterpret_cast<void **>(&pImgBuf32),nStride);");
|
|
if( !pImgBuf32 ) return;
|
|
|
|
size_t nBufSize = pImg->GetWidth() * pImg->GetHeight();
|
|
const XAlphaImage::Pixel *p = pImg->GetBuffer();
|
|
|
|
int nSrcStride = pImg->GetWidth(); /// 2011.02.23 - prodongi
|
|
|
|
DWORD* pDstColor;
|
|
DWORD* pSrcColor;
|
|
DWORD tempColor;
|
|
for(UINT y = 0; y < rcTexRect.bottom; y++ )
|
|
{
|
|
pDstColor = ( DWORD* )pImgBuf32; /// tex
|
|
pSrcColor = ( DWORD* )p; /// img
|
|
|
|
for( UINT x = 0; x < rcTexRect.right; x++ )
|
|
{
|
|
if( bRandomColor )
|
|
{
|
|
if( pSrcColor[x] != 0 )
|
|
{
|
|
tempColor = pSrcColor[x];
|
|
pDstColor[x] = DWORD((0xFF000000 & tempColor) | (GetNextRandColor() << 16) | (GetNextRandColor() << 8) | (GetNextRandColor()));
|
|
}
|
|
else
|
|
{
|
|
if (x < nSrcStride) /// 2011.02.23 - prodongi
|
|
pDstColor[x] = pSrcColor[x];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (x < nSrcStride) /// 2011.02.23 - prodongi
|
|
pDstColor[x] = pSrcColor[x];
|
|
}
|
|
}
|
|
|
|
pImgBuf32 += nStride;
|
|
p += nSrcStride;
|
|
}
|
|
|
|
//memcpy( pImgBuf16, pImg->GetBuffer(), dwTexWidth*dwTexHeight*2 );
|
|
|
|
m_spTexture->Unlock();
|
|
}
|
|
|
|
// 이제 Sprite에 Texture를 세팅해 주자
|
|
m_spResSprite->SetTexture(m_spTexture, &rcTexRect);
|
|
m_prSprite->SetRes(m_spResSprite);
|
|
|
|
if (isSpriteScroll) /// 2011.02.23 - prodongi
|
|
{
|
|
m_spTexture->SetTextOriImgRect(rcTexRect);
|
|
m_spTexture->SetTextOriImgSize(bufferImgWidth, bufferImgHeight);
|
|
m_prSprite->setScrollImgUv(bufferImgWidth, bufferImgHeight);
|
|
}
|
|
|
|
// Cache에도 등록
|
|
KTextCacheManager::GetInstance()->RegisterCache( strText.c_str(), color, lpszFontName, nSize,
|
|
dwWidth, dwHeight, dwFlag, color_fx, m_spTexture);
|
|
}
|
|
|
|
#endif
|
|
|
|
KTextRender::~KTextRender()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
|
|
void KTextRender::Clear()
|
|
{
|
|
m_spResSprite->SetTexture( NULL, NULL );
|
|
m_prSprite->SetRes( NULL );
|
|
|
|
SAFE_DELETE(m_prSprite);
|
|
SAFE_DELETE(m_pEmoticonLayerRender );
|
|
}
|
|
void KTextRender::SetPosition( float fXPos, float fYPos, float fZPos)
|
|
{
|
|
m_prSprite->SetPosition(fXPos,fYPos,fZPos);
|
|
|
|
if( m_pEmoticonLayerRender ) m_pEmoticonLayerRender->SetOffset( static_cast<int>(fXPos), static_cast<int>(fYPos) );
|
|
}
|
|
void KTextRender::SetVisibility( float vis )
|
|
{
|
|
m_prSprite->SetVisibility(vis);
|
|
}
|
|
|
|
void KTextRender::SetClipRect(const KRect & rcRect)
|
|
{
|
|
m_rcClipRect = rcRect;
|
|
m_prSprite->SetClipRect(&m_rcClipRect);
|
|
}
|
|
void KTextRender::Render( KViewportObject *viewport, bool isFront/* = false*/ )
|
|
{
|
|
viewport->Register(m_prSprite, isFront);
|
|
|
|
if( m_pEmoticonLayerRender ) m_pEmoticonLayerRender->Render( viewport, isFront );
|
|
}
|
|
|
|
#ifdef _COUNTRY_ME_
|
|
void KTextRender::InitTextRender( K3DRenderDevice * pDevice, int nCodePage, LPCTSTR strFontName )
|
|
{
|
|
m_pDevice = pDevice;
|
|
KFontManager::GetInstance()->Create( strFontName );
|
|
}
|
|
void KTextRender::DestroyAll()
|
|
{
|
|
KFontManager::GetInstance()->Destroy();
|
|
}
|
|
|
|
#else
|
|
void KTextRender::InitTextRender( K3DRenderDevice * pDevice )
|
|
{
|
|
m_pDevice = pDevice;
|
|
m_hDC = CreateCompatibleDC( NULL );
|
|
SetMapMode( m_hDC, MM_TEXT );
|
|
|
|
if( !s_pFreeType->IsInitialized() ) s_pFreeType->Init();
|
|
//if( !s_pFreeType->Init() ) assert(0 && "KTextRender::InitTextRender - Init Failed!!" );
|
|
}
|
|
|
|
|
|
void KTextRender::DestroyAll()
|
|
{
|
|
|
|
//SDEBUGLOG( "KTextRender::DestroyAll()" );
|
|
TEXT_FONT_INFO* info;
|
|
bool res = m_mapFontInfo.get_first_value( info );
|
|
while ( res )
|
|
{
|
|
delete info;
|
|
res = m_mapFontInfo.get_next_value( info );
|
|
}
|
|
m_mapFontInfo.clear();
|
|
s_pFreeType->DeInit();
|
|
delete s_pFreeType;
|
|
|
|
s_pFreeType = NULL;
|
|
|
|
DeleteDC(m_hDC);
|
|
}
|
|
#endif
|
|
|
|
|
|
int KTextRender::GetFontHeight( int nFontSize )
|
|
{
|
|
return (int)(nFontSize*1.5f);
|
|
}
|
|
|
|
void KTextRender::GetStringSize(LPCSTR lpszFontName, int nFontSize, BOOL bBold, LPCSTR lpszString, int nStringLen,
|
|
DWORD *pStringWidth, DWORD * pStringHeight)
|
|
{
|
|
TEXT_FONT_INFO * pInfo = _FindFont(lpszFontName, nFontSize);
|
|
|
|
if( pInfo && pInfo->bIsFreeType && m_bIncreaseEnglishFontSize )
|
|
nFontSize = incSizeIfNoMultiByte( lpszString, nFontSize );
|
|
|
|
std::string strString( lpszString );
|
|
|
|
for( size_t i = 0; i < strString.size(); ++i )
|
|
{
|
|
if( strString[i] == 0x1E )
|
|
strString[i] = '<';
|
|
if( strString[i] == 0x1F )
|
|
strString[i] = '>';
|
|
}
|
|
|
|
if( pInfo == NULL )
|
|
{
|
|
if( strlen(lpszFontName) > 0 )
|
|
{
|
|
KTextRender::AddFont(lpszFontName,nFontSize);
|
|
pInfo = _FindFont(lpszFontName, nFontSize);
|
|
}
|
|
}
|
|
|
|
// lenahyang 2012.09.06
|
|
if( pInfo == NULL )
|
|
{
|
|
pInfo = _FindFont( "default", nFontSize );
|
|
|
|
if( pInfo == NULL )
|
|
{
|
|
*pStringWidth = 0;
|
|
*pStringHeight = 0;
|
|
return;
|
|
}
|
|
}
|
|
|
|
assert( pInfo && "TEXT_FONT_INFO == NULL 여기 어쩌다 들어 오는데 고치시오~" );
|
|
|
|
if( pInfo && pInfo->bIsFreeType )
|
|
{
|
|
// assert( _CrtCheckMemory() );
|
|
//SDEBUGLOG("KTextRender::GetStringSize - begin (bIsFreeType)");
|
|
//SDEBUGLOG("\tKTextRender::GetStringSize - %p, %s, %d, %s, %d",s_pFreeType, lpszFontName, nFontSize, lpszString, nStringLen);
|
|
|
|
wchar_t *pBuffer = new wchar_t[ nStringLen+1 ];
|
|
// assert( _CrtCheckMemory() );
|
|
int len = ::MultiByteToWideChar( m_nDefaultCodePage, 0, strString.c_str(), nStringLen, pBuffer, nStringLen );
|
|
// assert( _CrtCheckMemory() );
|
|
|
|
pBuffer[len] = 0;
|
|
// assert( _CrtCheckMemory() );
|
|
|
|
// 2010.07.20 - prodongi
|
|
if( !s_pFreeType->GetSize( lpszFontName, pBuffer, (int*)pStringWidth, (int*)pStringHeight, nFontSize*m_fFreeTypeSizeRatio, pInfo->bHinting ) )
|
|
//if( !s_pFreeType->GetSize( lpszFontName, pBuffer, (int*)pStringWidth, (int*)pStringHeight, nFontSize*m_fFreeTypeSizeRatio ) )
|
|
{
|
|
//SDEBUGLOG("\tKTextRender::GetStringSize - end1");
|
|
*pStringWidth = 0;
|
|
*pStringHeight = 0;
|
|
delete [] pBuffer;
|
|
//SDEBUGLOG("KTextRender::GetStringSize - end1.end");
|
|
return;
|
|
}
|
|
//SDEBUGLOG("\tKTextRender::GetStringSize - end2");
|
|
|
|
(*pStringHeight) = GetFontHeight( nFontSize );
|
|
delete [] pBuffer;
|
|
|
|
//SDEBUGLOG("KTextRender::GetStringSize - end2.end");
|
|
return;
|
|
}
|
|
|
|
WIN32_TEXT_FONT_INFO *pWin32Info = (WIN32_TEXT_FONT_INFO *)pInfo;
|
|
|
|
|
|
HFONT hFontOld;
|
|
|
|
if(bBold)
|
|
{
|
|
hFontOld = (HFONT)::SelectObject(m_hDC,pWin32Info->hBoldFont);
|
|
}
|
|
else
|
|
hFontOld = (HFONT)::SelectObject(m_hDC, pWin32Info->hDefaultFont);
|
|
|
|
SIZE size;
|
|
GetTextExtentPoint32( m_hDC, strString.c_str(), nStringLen, &size );
|
|
*pStringWidth = size.cx; *pStringHeight = size.cy;
|
|
|
|
|
|
}
|
|
|
|
void KTextRender::SetFontHinting( LPCSTR lpszFontName, bool bHinting )
|
|
{
|
|
TEXT_FONT_INFO* pFontInfo = _FindFont( lpszFontName, -1 );
|
|
if ( pFontInfo )
|
|
pFontInfo->SetHinting( bHinting );
|
|
}
|
|
|
|
bool KTextRender::AddFreeTypeFont( LPCSTR lpszFontName, LPCSTR lpszFontFileName )
|
|
{
|
|
// 이미 Load한 Font는 Add할 필요가 없다.
|
|
if(_FindFont(lpszFontName,-1) )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool rSuc;
|
|
FREETYPE_TEXT_FONT_INFO *pInfo = new FREETYPE_TEXT_FONT_INFO( lpszFontName, lpszFontFileName, &rSuc );
|
|
|
|
|
|
if(rSuc)
|
|
{
|
|
// SDEBUGLOG( "AddFreeTypeFont : %s %s\n", lpszFontName, lpszFontFileName );
|
|
|
|
hashPr_font::Key key( lpszFontName, -1 );
|
|
m_mapFontInfo.add( key, pInfo );
|
|
}
|
|
else
|
|
{
|
|
SAFE_DELETE(pInfo);
|
|
}
|
|
|
|
return rSuc;
|
|
}
|
|
|
|
void KTextRender::AddFont(LPCSTR lpszFontName, int nFontSize )
|
|
{
|
|
// 이미 Load한 Font는 Add할 필요가 없다.
|
|
if(_FindFont(lpszFontName,nFontSize) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef _COUNTRY_TL_
|
|
DWORD iCharSet = THAI_CHARSET;
|
|
#else
|
|
DWORD iCharSet = DEFAULT_CHARSET;
|
|
#endif
|
|
|
|
WIN32_TEXT_FONT_INFO * pInfo = WIN32_TEXT_FONT_INFO::CreateTextFont();
|
|
|
|
int nHeight = -MulDiv( nFontSize, (INT)(GetDeviceCaps(m_hDC, LOGPIXELSY)), 72 );
|
|
|
|
// 미리 폰트를 생성하자.
|
|
pInfo->hDefaultFont = ::CreateFont( nHeight, 0, 0, 0, FW_NORMAL, FALSE,
|
|
FALSE, FALSE, iCharSet, OUT_DEFAULT_PRECIS,
|
|
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
|
|
DEFAULT_PITCH, lpszFontName );
|
|
|
|
int nCWeight = FW_BOLD;
|
|
//일본 비스타 버전에서 BOLD 폰트가 깨지는 문제가 발생.. 뭐냐!!!
|
|
if( s_bIsOsVista && ( s_strLocale.length() > 0 && _stricmp( s_strLocale.c_str(), "Shift-JIS" ) == 0 ) )
|
|
nCWeight = FW_SEMIBOLD;
|
|
|
|
pInfo->hBoldFont = ::CreateFont(nHeight,0,0,0,nCWeight, FALSE,
|
|
FALSE, FALSE, iCharSet, OUT_DEFAULT_PRECIS,
|
|
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
|
|
DEFAULT_PITCH, lpszFontName );
|
|
|
|
pInfo->hUnderLineFont = ::CreateFont( nHeight, 0, 0, 0, FW_NORMAL, FALSE,
|
|
TRUE, FALSE, iCharSet, OUT_DEFAULT_PRECIS,
|
|
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
|
|
DEFAULT_PITCH, lpszFontName);
|
|
|
|
pInfo->hStrikeOutFont = ::CreateFont( nHeight, 0, 0, 0, FW_NORMAL, FALSE,
|
|
FALSE, TRUE, iCharSet, OUT_DEFAULT_PRECIS,
|
|
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
|
|
DEFAULT_PITCH, lpszFontName);
|
|
|
|
hashPr_font::Key key( lpszFontName, nFontSize );
|
|
m_mapFontInfo.add( key, pInfo );
|
|
|
|
//_oprint( "AddFont : %s %d\t\n", lpszFontName, nFontSize );
|
|
|
|
//#ifdef _DEBUG
|
|
// const char* pTempText = "abc defg, hijklmn";
|
|
// DWORD nW, nH;
|
|
// GetStringSize( lpszFontName, nFontSize, false, pTempText, strlen(pTempText), &nW, &nH );
|
|
// _oprint( "Text Len : [%d] [%d] %s\n", nW, nH, pTempText );
|
|
//#endif
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
KTextRender::TEXT_FONT_INFO * KTextRender::_FindFont(LPCSTR lpszFontName, int nFontSize)
|
|
{
|
|
if( strlen( lpszFontName ) <= 0 ) return NULL;
|
|
|
|
TEXT_FONT_INFO* info;
|
|
hashPr_font::Key key( lpszFontName, nFontSize );
|
|
if ( m_mapFontInfo.lookup( key, info ) )
|
|
{
|
|
return info;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
// MIMI 2005/08/10
|
|
void KTextRender::CheckEmoticon( std::string & strText, LPCSTR lpszFontName, int nFontSize, DWORD dwFlag, DWORD & dwWidth, DWORD & dwHeight, bool bStaticSize, float fZPos )
|
|
{
|
|
//_LEAK_SUN
|
|
SAFE_DELETE( m_pEmoticonLayerRender );
|
|
|
|
m_pEmoticonLayerRender = new KTextEmoticonRender; // [MEMORY_LEAK] 2012. 3. 2 - marine 메모리 해제해줌..
|
|
m_pEmoticonLayerRender->CheckEmoticon( strText, lpszFontName, nFontSize, dwFlag, dwWidth, dwHeight, bStaticSize, fZPos );
|
|
}
|
|
const int KTextRender::GetTextSize( const char* szBuf )
|
|
{
|
|
// 이모티콘 필터링 한 후 글자수 리턴
|
|
//return m_pEmoticonLayerRender->GetTextSize(szBuf);
|
|
return KTextEmoticonRender::GetTextSize(szBuf);
|
|
}
|
|
void KTextRender::GetEmoticonFilterText( std::string & strBuf )
|
|
{
|
|
KTextEmoticonRender::GetText( strBuf );
|
|
}
|
|
|
|
// KDebugRenderer Implement
|
|
KDebugRenderer *KDebugRenderer::s_pDebugRenderer = NULL;
|
|
KDebugRenderer::KDebugRenderer()
|
|
{
|
|
m_vPosition = K3DVector(0.0f,0.0f,KDRE_RENDER_LAYER);
|
|
}
|
|
|
|
void KDebugRenderer::Clear()
|
|
{
|
|
for(unsigned int i = 0;i < m_vtDebugItem.size(); ++i)
|
|
{
|
|
m_vtDebugItem.at(i).Destroy();
|
|
}
|
|
m_vtDebugItem.clear();
|
|
}
|
|
KDebugRenderer & KDebugRenderer::GetInstance()
|
|
{
|
|
static KDebugRenderer debugObj;
|
|
return debugObj;
|
|
}
|
|
|
|
void KDebugRenderer::Render(KViewportObject * pViewport, DWORD flag, const K3DMatrix * pAttachMat )
|
|
{
|
|
float fYPos = m_vPosition.y;
|
|
for(unsigned int i = 0; i <m_vtDebugItem.size(); ++i)
|
|
{
|
|
m_vtDebugItem.at(i).SetPosition(m_vPosition.x, fYPos, m_vPosition.z);
|
|
m_vtDebugItem.at(i).Render(pViewport);
|
|
if(m_vtDebugItem.at(i).pTextPharse)
|
|
{
|
|
fYPos += m_vtDebugItem.at(i).pTextPharse->GetHeight();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool KDebugRenderer::AddDebugItem(LPCSTR lpszDebugName, LPCSTR lpszDebugInfo)
|
|
{
|
|
if( _FindDebugItem(lpszDebugName) != -1)
|
|
return false;
|
|
|
|
DEBUG_ITEM item;
|
|
item.SetDebugInfo(lpszDebugName, lpszDebugInfo);
|
|
m_vtDebugItem.push_back(item);
|
|
|
|
return true;
|
|
}
|
|
bool KDebugRenderer::AddDebugItem(LPCSTR lpszDebugName, double DebugInfo)
|
|
{
|
|
char buff[512];
|
|
sprintf(buff,"%.1f", DebugInfo);
|
|
return AddDebugItem(lpszDebugName, buff);
|
|
}
|
|
|
|
bool KDebugRenderer::RemoveDebugItem(LPCSTR lpszDebugName)
|
|
{
|
|
|
|
int nIndex = _FindDebugItem(lpszDebugName);
|
|
|
|
if(nIndex < 0)
|
|
return false;
|
|
|
|
m_vtDebugItem.at(nIndex).Destroy();
|
|
m_vtDebugItem.erase(m_vtDebugItem.begin() + nIndex);
|
|
return true;
|
|
}
|
|
bool KDebugRenderer::ModifyDebugItem(LPCSTR lpszDebugName, LPCSTR lpszDebugInfo)
|
|
{
|
|
int nIndex = _FindDebugItem(lpszDebugName);
|
|
|
|
if(nIndex < 0)
|
|
return false;
|
|
|
|
m_vtDebugItem.at(nIndex).SetDebugInfo(lpszDebugName, lpszDebugInfo);
|
|
return true;
|
|
}
|
|
bool KDebugRenderer::ModifyDebugItem(LPCSTR lpszDebugName, double DebugInfo)
|
|
{
|
|
char buff[512];
|
|
sprintf(buff,"%.1f", DebugInfo);
|
|
return ModifyDebugItem(lpszDebugName, buff);
|
|
}
|
|
int KDebugRenderer::_FindDebugItem(LPCSTR lpszDebugName)
|
|
{
|
|
for(unsigned int i = 0; i < m_vtDebugItem.size(); ++i)
|
|
{
|
|
if(m_vtDebugItem.at(i).sDebugName == lpszDebugName)
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
void KDebugRenderer::DEBUG_ITEM::Destroy()
|
|
{
|
|
SAFE_DELETE(pTextPharse);
|
|
}
|
|
void KDebugRenderer::DEBUG_ITEM::SetDebugInfo(LPCSTR lpszDebugName, LPCSTR lpszDebugInfo)
|
|
{
|
|
sDebugName = lpszDebugName;
|
|
SAFE_DELETE(pTextPharse);
|
|
DWORD dwWidth =512;
|
|
KSize size = KTextPhrase::GetStringSize(lpszDebugInfo, dwWidth);
|
|
|
|
if(size.width == 0 || size.height == 0)
|
|
return;
|
|
|
|
pTextPharse = new KTextPhrase(size.width, size.height);
|
|
#ifdef _COUNTRY_ME_
|
|
pTextPharse->SetAlign(KTextParagraph::KTALIGN_LEFT | KTextParagraph::KTALIGN_TOP);
|
|
#else
|
|
pTextPharse->SetAlign(KTextRender::KTALIGN_LEFT | KTextRender::KTALIGN_TOP);
|
|
#endif
|
|
pTextPharse->AddString( lpszDebugInfo);
|
|
}
|
|
void KDebugRenderer::DEBUG_ITEM::SetPosition(float fXPos, float fYPos, float fZPos)
|
|
{
|
|
if(pTextPharse)
|
|
{
|
|
pTextPharse->SetPosition(fXPos,fYPos,fZPos);
|
|
}
|
|
}
|
|
void KDebugRenderer::DEBUG_ITEM::Render(KViewportObject * pViewportObject)
|
|
{
|
|
if(pTextPharse)
|
|
{
|
|
pTextPharse->Render(pViewportObject);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//추가
|
|
int KTextRender::CalcCarretPos( const char *szAlias, const wchar_t *wszString, int x,int nFontSize, int ft )
|
|
{
|
|
// assert( _CrtCheckMemory() );
|
|
return KTextRender::s_pFreeType->CalcCarretPos(szAlias, nFontSize, ft,wszString, x );
|
|
}
|
|
|
|
void KTextRender::GetFreeTypeTextWidth( const wchar_t *text, size_t len, LPSIZE lpSize )
|
|
{
|
|
lpSize->cx = 0;
|
|
lpSize->cy = 13;
|
|
// assert( _CrtCheckMemory() );
|
|
KTextRender::s_pFreeType->GetSize( KTextRender::KDEFAULT_FONT_NAME, text, (int*)&lpSize->cx, NULL, 13 );
|
|
}
|
|
|
|
// 2010.05.06 - prodongi
|
|
void KTextRender::modifyEmoticonSize(std::string const& aniName, int width, int height)
|
|
{
|
|
if (!m_pEmoticonLayerRender) return ;
|
|
m_pEmoticonLayerRender->modifyEmoticonSize(aniName, width, height);
|
|
}
|
|
|
|
void KTextRender::setSpriteScroll(bool scroll, DWORD type, float v, float margin) /// 2011.01.18 - prodongi
|
|
{
|
|
m_prSprite->initScroll(scroll, type, v, margin);
|
|
}
|
|
|
|
#ifdef _COUNTRY_ME_
|
|
|
|
|
|
BYTE Get5x5FilteredAlphaValue( LPBYTE pSrc, int x, int y, int w, int h, int nStride )
|
|
{
|
|
static double dWeight[5][5] =
|
|
{
|
|
{ 0.0, 0.1, 0.2, 0.1, 0.0 },
|
|
{ 0.1, 0.3, 0.5, 0.3, 0.1 },
|
|
{ 0.2, 0.5, 0.7, 0.5, 0.2 },
|
|
{ 0.1, 0.3, 0.5, 0.3, 0.1 },
|
|
{ 0.0, 0.1, 0.2, 0.1, 0.0 }
|
|
};
|
|
|
|
double dAlpha = 0.;
|
|
LPDWORD pdwValue;
|
|
KColor color;
|
|
|
|
for ( int i = -2; i < 3; ++i )
|
|
{
|
|
if ( y + i >= 0 && y + i < h )
|
|
{
|
|
for ( int j = -2; j < 3; ++j )
|
|
{
|
|
if ( x + j >= 0 && x + j < w )
|
|
{
|
|
pdwValue = (LPDWORD)(pSrc + (x + j) * 4 + (y + i) * nStride);
|
|
color = *pdwValue;
|
|
dAlpha += color.a * dWeight[i + 2][j + 2];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ( dAlpha > 255 )
|
|
dAlpha = 255;
|
|
return (BYTE)(dAlpha);
|
|
}
|
|
|
|
void BitBlt_Premultiplied2Nonmultiplied( LPVOID pSrc, LPVOID pDst, int nWidth, int nHeight, int nSrcStride, int nDstStride, bool bGlow )
|
|
{
|
|
LPBYTE pbSrc = (LPBYTE)pSrc;
|
|
LPBYTE pbDst = (LPBYTE)pDst;
|
|
LPDWORD pdwSrc, pdwDst;
|
|
|
|
KColor pxSrc, pxDst;
|
|
int x, y;
|
|
|
|
if ( bGlow )
|
|
{
|
|
for ( y = 0; y < nHeight; y++ )
|
|
{
|
|
pdwDst = (DWORD *)pbDst;
|
|
|
|
for( x = 0; x < nWidth; x++ )
|
|
{
|
|
BYTE bAlpha = Get5x5FilteredAlphaValue( pbSrc, x, y, nWidth, nHeight, nSrcStride );
|
|
|
|
if ( bAlpha > 0 )
|
|
{
|
|
pxDst.a = bAlpha;
|
|
pxDst.g = 0;
|
|
pxDst.b = 74;
|
|
pxDst.r = 128;
|
|
*pdwDst++ = pxDst.color;
|
|
}
|
|
else
|
|
*pdwDst++ = 0;
|
|
}
|
|
pbDst += nDstStride;
|
|
}
|
|
}
|
|
|
|
pbSrc = (LPBYTE)pSrc;
|
|
pbDst = (LPBYTE)pDst;
|
|
|
|
for ( y = 0; y < nHeight; y++ )
|
|
{
|
|
pdwSrc = (DWORD *)pbSrc;
|
|
pdwDst = (DWORD *)pbDst;
|
|
|
|
for( x = 0; x < nWidth; x++ )
|
|
{
|
|
pxSrc.color = *pdwSrc++;
|
|
|
|
if ( pxSrc.a > 0 )
|
|
{
|
|
pxDst.r = pxSrc.r * 255 / pxSrc.a;
|
|
pxDst.g = pxSrc.g * 255 / pxSrc.a;
|
|
pxDst.b = pxSrc.b * 255 / pxSrc.a;
|
|
pxDst.a = pxSrc.a;
|
|
*pdwDst++ = pxDst.color;
|
|
}
|
|
else
|
|
*pdwDst++;
|
|
}
|
|
|
|
pbSrc += nSrcStride;
|
|
pbDst += nDstStride;
|
|
}
|
|
}
|
|
|
|
KTextRender::KTextRender( KTextParagraph* pString, DWORD dwWidth, DWORD dwHeight, DWORD dwLineGap, DWORD dwAlign, bool bRandomColor )
|
|
: m_dwWidth( dwWidth ), m_dwHeight( dwHeight ), m_pEmoticonLayerRender( 0 )
|
|
{
|
|
// InitTextRender가 불려지지 않았으므로
|
|
if(!m_pDevice)
|
|
{
|
|
assert(false && "please call InitTextRender");
|
|
}
|
|
|
|
m_prSprite = new KSpritePrimitive(false);
|
|
m_spResSprite = new KResSprite;
|
|
|
|
if ( dwWidth == 0 || dwHeight == 0 )
|
|
return;
|
|
|
|
|
|
DWORD dwOldHeight = dwHeight;
|
|
|
|
m_spTexture = KTextCacheManager::GetInstance()->FindCache(
|
|
pString->GetString().c_str(),
|
|
pString->GetAttr()->dwColor,
|
|
pString->GetAttr()->strFontName.c_str(),
|
|
pString->GetAttr()->nFontSize,
|
|
dwWidth, dwHeight,
|
|
pString->GetAttrHash(),
|
|
pString->GetAttr()->bShadow + pString->GetAttr()->bBold * 2);
|
|
|
|
if (m_spTexture != NULL)
|
|
{
|
|
m_spResSprite->SetTexture(m_spTexture, NULL);
|
|
m_prSprite->SetRes(m_spResSprite);
|
|
return;
|
|
}
|
|
|
|
// 2010.09.07 왜 주석 처리가 되어 있나??? - prodongi
|
|
KTextLayout layout( dwWidth, dwHeight, dwLineGap, dwAlign );
|
|
|
|
layout.Render( pString );
|
|
|
|
|
|
|
|
int nStride;
|
|
char * pImgBuf32 = NULL;
|
|
|
|
KRect rcTexRect;
|
|
rcTexRect.left = 0; rcTexRect.top = 0; rcTexRect.right = dwWidth; rcTexRect.bottom = dwHeight;
|
|
|
|
m_spTexture = m_pDevice->CreateTexture(dwWidth,dwHeight, K3DFMT_A8R8G8B8 );
|
|
assert( m_spTexture && "m_spTexture = m_pDevice->CreateTexture(dwTexWidth,dwTexHeight, K3DFMT_A8R8G8B8 )");
|
|
if(m_spTexture == NULL)
|
|
return;
|
|
|
|
m_spTexture->LockRect(&rcTexRect, reinterpret_cast<void **>(&pImgBuf32), nStride);
|
|
assert( pImgBuf32 && "m_spTexture->LockRect(&rcTexRect, reinterpret_cast<void **>(&pImgBuf32),nStride);");
|
|
if( !pImgBuf32 )
|
|
return;
|
|
|
|
// 2010.09.07 왜 주석 처리가 되어 있나??? - prodongi
|
|
BitBlt_Premultiplied2Nonmultiplied( layout.GetImage(), pImgBuf32, dwWidth, dwHeight, layout.GetImageStride(), nStride, pString->GetAttr()->bGlow );
|
|
|
|
m_spTexture->Unlock();
|
|
|
|
m_spResSprite->SetTexture(m_spTexture, &rcTexRect);
|
|
|
|
m_prSprite->SetRes(m_spResSprite);
|
|
|
|
KTextCacheManager::GetInstance()->RegisterCache(
|
|
pString->GetString().c_str(),
|
|
pString->GetAttr()->dwColor,
|
|
pString->GetAttr()->strFontName.c_str(),
|
|
pString->GetAttr()->nFontSize,
|
|
dwWidth, dwHeight,
|
|
pString->GetAttrHash(),
|
|
pString->GetAttr()->bShadow + pString->GetAttr()->bBold * 2,
|
|
m_spTexture);
|
|
}
|
|
|
|
|
|
#endif |