385 lines
10 KiB
C++
385 lines
10 KiB
C++
|
|
#include "stdafx.h"
|
|
#include "KTextEmoticonRender.h"
|
|
#include "KViewport.h"
|
|
#include "KPrimitiveSprite.h"
|
|
#include "KResourceManager.h"
|
|
#include <toolkit/XStringUtil.h>
|
|
#include "KTextRender.h"
|
|
|
|
namespace
|
|
{
|
|
const int g_nEmoticonFilterOffset = 3;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// KTextEmoticon
|
|
KTextEmoticon::KTextEmoticon( int nType, int nOffsetX, int nOffsetY, int nWidth, int nHeight, const char* szAniName, const char* szSprName, float fZPos )
|
|
: m_nType( nType )
|
|
, m_nOffsetX( nOffsetX )
|
|
, m_nOffsetY( nOffsetY )
|
|
, m_nWidth( nWidth )
|
|
, m_nHeight( nHeight )
|
|
, m_strAniName( szAniName )
|
|
, m_strSprName( szSprName )
|
|
, m_pPrimitive( NULL )
|
|
, m_rcRegion( KRect(0, 0, 0, 0) )
|
|
, m_fZPos(fZPos)
|
|
{
|
|
|
|
}
|
|
|
|
KTextEmoticon::~KTextEmoticon()
|
|
{
|
|
SAFE_DELETE(m_pPrimitive);
|
|
}
|
|
bool KTextEmoticon::Initialize( bool bStaticSize )
|
|
{
|
|
if( m_pPrimitive ) SAFE_DELETE(m_pPrimitive);
|
|
|
|
m_pPrimitive = new KSpritePrimitive;
|
|
|
|
KResSprite* pRes = KSpriteManager::GetManager()->GetSpriteSet(m_strSprName.c_str())->GetSpriteRes( m_strAniName.c_str(), 0 );
|
|
|
|
if( pRes == NULL || pRes->GetTexture() == NULL )
|
|
{
|
|
std::string strMsg;
|
|
XStringUtil::Format( strMsg, "SetEmoticon:: emoticon 생성 실패 : spr-%s, ani-%s", m_strSprName.c_str(), m_strAniName.c_str() );
|
|
assert( 0 && strMsg.c_str() );
|
|
|
|
SAFE_DELETE(m_pPrimitive);
|
|
|
|
return false;
|
|
}
|
|
|
|
// 원본 이미지의 크기를 따른다
|
|
if( !bStaticSize )
|
|
{
|
|
m_nWidth = pRes->GetSourceRect().GetWidth();
|
|
m_nHeight = pRes->GetSourceRect().GetHeight();
|
|
}
|
|
|
|
m_pPrimitive->SetRes( pRes );
|
|
m_pPrimitive->SetTargetSize( (float)m_nWidth, (float)m_nHeight );
|
|
m_pPrimitive->SetPosition( K3DVector(0, 0, m_fZPos ) );
|
|
|
|
return true;
|
|
}
|
|
void KTextEmoticon::SetOffset( int nX, int nY )
|
|
{
|
|
m_rcRegion.left = m_nOffsetX + nX;
|
|
m_rcRegion.top = m_nOffsetY + nY;
|
|
m_rcRegion.right = m_rcRegion.left + m_nWidth;
|
|
m_rcRegion.bottom = m_rcRegion.top + m_nHeight;
|
|
|
|
if( m_pPrimitive ) m_pPrimitive->SetPosition( static_cast<float>(m_rcRegion.left), static_cast<float>(m_rcRegion.top), m_fZPos );
|
|
}
|
|
void KTextEmoticon::Render( KViewportObject* pViewport, bool bIsFront )
|
|
{
|
|
if( m_pPrimitive == NULL ) return;
|
|
pViewport->Register( m_pPrimitive, bIsFront );
|
|
}
|
|
|
|
|
|
// 2010.05.06 - prodongi
|
|
void KTextEmoticon::setSize(std::string const& aniName, int width, int height)
|
|
{
|
|
if (width < 0 && height < 0)
|
|
return ;
|
|
if (m_strAniName != aniName)
|
|
return ;
|
|
|
|
if (width > 0) m_nWidth = width;
|
|
if (height > 0) m_nHeight = height;
|
|
|
|
m_pPrimitive->SetTargetSize( (float)m_nWidth, (float)m_nHeight );
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// KTextEmoticonRender
|
|
|
|
std::vector< EMOTICON_DATA > KTextEmoticonRender::s_vFilterList;
|
|
std::string KTextEmoticonRender::s_strSprName;
|
|
|
|
KTextEmoticonRender::~KTextEmoticonRender()
|
|
{
|
|
Clear();
|
|
}
|
|
void KTextEmoticonRender::Clear()
|
|
{
|
|
//_LEAK_SUN
|
|
//s_vFilterList.clear(); //이거하믄 이모티콘 안나옴.
|
|
|
|
std::vector<KTextEmoticon*>::iterator it = m_vecEmoticonList.begin();
|
|
while( it != m_vecEmoticonList.end() )
|
|
{
|
|
SAFE_DELETE(*it);
|
|
++it;
|
|
}
|
|
|
|
m_vecEmoticonList.clear();
|
|
}
|
|
|
|
void KTextEmoticonRender::Render( KViewportObject* pViewport, bool bIsFront )
|
|
{
|
|
if( m_vecEmoticonList.empty() ) return;
|
|
|
|
std::vector<KTextEmoticon*>::iterator it = m_vecEmoticonList.begin();
|
|
while( it != m_vecEmoticonList.end() )
|
|
{
|
|
(*it)->Render( pViewport, bIsFront );
|
|
it++;
|
|
}
|
|
}
|
|
|
|
void KTextEmoticonRender::CheckEmoticon( std::string & strText, const char* szFontName, int nFontSize, DWORD dwFlag, DWORD & dwWidth, DWORD & dwHeight, bool bStaticSize, float fZPos )
|
|
{
|
|
Clear();
|
|
m_bStaticSize = bStaticSize;
|
|
|
|
//for( int i = 0; g_szEmoticonFilter[i] != NULL; i++ )
|
|
// CheckFiltering( g_szEmoticonFilter[i], strText, szFontName, nFontSize, dwFlag, dwWidth );
|
|
|
|
// 텍스트 처음부터 끝까지 읽으면서 필터링 한다.
|
|
std::string str = strText;
|
|
|
|
size_t begin_pos = 0;
|
|
for( size_t pos = 0; pos <= str.size(); )
|
|
{
|
|
std::string strTemp = str.substr( begin_pos, pos-begin_pos );
|
|
if( strTemp.empty() )
|
|
{
|
|
pos++;
|
|
continue;
|
|
}
|
|
|
|
const char* szFilter = GetExistFilter( strTemp.c_str() );
|
|
if( szFilter )
|
|
{
|
|
CheckFiltering( szFilter, strText, szFontName, nFontSize, dwFlag, dwWidth, dwHeight, fZPos );
|
|
begin_pos = pos;
|
|
}
|
|
|
|
pos++;
|
|
}
|
|
}
|
|
const char* KTextEmoticonRender::GetExistFilter( const char* szText )
|
|
{
|
|
std::string strText = szText;
|
|
|
|
for( unsigned int i = 0; s_vFilterList.size()>i; i++ )
|
|
{
|
|
if( strText.find( s_vFilterList[i].strFilter.c_str() ) != strText.npos )
|
|
return s_vFilterList[i].strFilter.c_str();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
void KTextEmoticonRender::CheckFiltering( const char* szFilter, std::string & strText, const char* szFontName, int nFontSize, DWORD dwFlag, DWORD & dwWidth, DWORD & dwHeight, float fZPos )
|
|
{
|
|
size_t pos = strText.find(szFilter);
|
|
if( pos == strText.npos ) return;
|
|
|
|
size_t emoticon_delta = 2;
|
|
if( !m_bStaticSize ) emoticon_delta = 4;
|
|
|
|
const char *pEmotionAniName = NULL;
|
|
for( size_t i = 0; s_vFilterList.size()>i; i++ )
|
|
{
|
|
if( s_vFilterList[i].strFilter.find( szFilter ) != strText.npos )
|
|
{
|
|
pEmotionAniName = s_vFilterList[i].strAniName.c_str();
|
|
break;
|
|
}
|
|
}
|
|
|
|
for( pos = 0; pos != strText.npos; )
|
|
{
|
|
pos = strText.find( szFilter, pos );
|
|
if( pos == strText.npos ) break;
|
|
else
|
|
{
|
|
// 이모티콘 자리만 남기고 나머지 텍스트는 지워주어야 한다.
|
|
// ex) "하하하" 를 하나의 이모티콘으로 처리할 경우, "하"만 남기고 하하는 지워주어야 한다.
|
|
size_t size_offset = ::strlen(szFilter);
|
|
if( size_offset > emoticon_delta ) strText.erase( pos+emoticon_delta, size_offset-emoticon_delta );
|
|
else if( size_offset < emoticon_delta )
|
|
{
|
|
size_t temp = size_offset;
|
|
while( emoticon_delta-temp > 0 )
|
|
{
|
|
strText.insert( pos+size_offset, "^", 1 );
|
|
++temp;
|
|
}
|
|
}
|
|
|
|
std::string str;
|
|
str = strText.substr( 0, pos );
|
|
|
|
// 이모티콘 pos 구한다.
|
|
// 이모티콘 필터 텍스트 직전까지의 텍스쳐 크기가 pos 이다.
|
|
DWORD dwStringWidth, dwStringHeight;
|
|
dwStringWidth = 0;
|
|
dwStringHeight = 0;
|
|
bool bBold = dwFlag & KTextRender::KTFLAG_BOLD;
|
|
KTextRender::GetStringSize( szFontName, nFontSize, bBold, str.c_str(), static_cast<int>(str.size()), &dwStringWidth, &dwStringHeight );
|
|
|
|
// 이모티콘의 크기는 폰트 크기로부터 여분을 더한 크기.
|
|
// g_nEmoticonFilterOffset 을 조정하면 이모티콘 크기 조정 가능
|
|
int nEmoticonSize = nFontSize + g_nEmoticonFilterOffset;
|
|
// 이모티콘 타입 임시로
|
|
int nEmoticonType = KTextEmoticon::TYPE_NORMAL;
|
|
/*
|
|
if( ::_stricmp(szFilter, g_szEmoticonFilter[5]) == 0 || ::_stricmp(szFilter, g_szEmoticonFilter[6]) == 0 )
|
|
nEmoticonType = KTextEmoticon::TYPE_HARMFUL;
|
|
*/
|
|
// end 이모티콘 타입 임시
|
|
KTextEmoticon* pEmoticon = new KTextEmoticon( nEmoticonType, dwStringWidth, 0, nEmoticonSize, nEmoticonSize, pEmotionAniName, s_strSprName.c_str(), fZPos );
|
|
if( !pEmoticon->Initialize( m_bStaticSize ) )
|
|
{
|
|
pos += emoticon_delta;
|
|
delete pEmoticon;
|
|
continue;
|
|
}
|
|
m_vecEmoticonList.push_back( pEmoticon );
|
|
|
|
// 필터 텍스트의 크기를 알아낸다.
|
|
// 이부분은 미리 가지고 있어도 좋다
|
|
DWORD dwFilterWidth;
|
|
DWORD dwFilterHeight;
|
|
KTextRender::GetStringSize( szFontName, nFontSize, bBold, szFilter, static_cast<int>(::strlen(szFilter)), &dwFilterWidth, &dwFilterHeight );
|
|
|
|
// 필터 텍스트 크기 만큼 전체 텍스트 텍스쳐에서 빼주어서 전체 텍스트 텍스쳐 크기 보정한다.
|
|
int nCheckWidth = dwWidth;
|
|
|
|
nCheckWidth -= dwFilterWidth;
|
|
if( nCheckWidth < 0 ) nCheckWidth = 0;
|
|
|
|
dwWidth = nCheckWidth;
|
|
|
|
if( m_bStaticSize )
|
|
{
|
|
dwWidth += nEmoticonSize;
|
|
strText.replace( pos, emoticon_delta, " " );
|
|
}
|
|
else
|
|
{
|
|
/// 2011.05.11 redmine #15 strText가 바뀌면서 width가 변해 버리기 때문에, 다시 계산해 줘야 된다. - prodongi
|
|
DWORD h;
|
|
strText.replace( pos, emoticon_delta, " " );
|
|
dwHeight = pEmoticon->GetHeight();
|
|
KTextRender::GetStringSize( szFontName, nFontSize, bBold, strText.c_str(), strText.length(), &dwWidth, &h );
|
|
}
|
|
|
|
break;
|
|
}
|
|
pos += emoticon_delta;
|
|
}
|
|
}
|
|
void KTextEmoticonRender::SetOffset( int nOffsetX, int nOffsetY )
|
|
{
|
|
if( m_vecEmoticonList.empty() ) return;
|
|
|
|
std::vector<KTextEmoticon*>::iterator it = m_vecEmoticonList.begin();
|
|
while( it != m_vecEmoticonList.end() )
|
|
{
|
|
(*it)->SetOffset( nOffsetX, nOffsetY );
|
|
it++;
|
|
}
|
|
}
|
|
|
|
const int KTextEmoticonRender::GetTextSize( const char* szBuf )
|
|
{
|
|
if( szBuf == NULL ) return -1;
|
|
|
|
std::string str = szBuf;
|
|
size_t size_text = str.size();
|
|
|
|
size_t begin_pos = 0;
|
|
for( size_t pos = 0; pos <= str.size(); )
|
|
{
|
|
std::string strTemp = str.substr( begin_pos, pos-begin_pos );
|
|
if( strTemp.empty() )
|
|
{
|
|
pos++;
|
|
continue;
|
|
}
|
|
|
|
const char* szFilter = GetExistFilter( strTemp.c_str() );
|
|
if( szFilter )
|
|
{
|
|
size_t size_offset = ::strlen(szFilter);
|
|
if( size_offset > 2 )
|
|
size_text -= (size_offset-2);
|
|
|
|
begin_pos = pos;
|
|
}
|
|
|
|
pos++;
|
|
}
|
|
|
|
return static_cast<int>(size_text);
|
|
}
|
|
void KTextEmoticonRender::GetText( std::string & strBuf )
|
|
{
|
|
if( strBuf.empty() ) return;
|
|
|
|
//Emoticon symbol text 삭제
|
|
for( size_t i = 0; s_vFilterList.size()>i; i++ )
|
|
{
|
|
while( true )
|
|
{
|
|
size_t pos = strBuf.find( s_vFilterList[i].strFilter.c_str() );
|
|
|
|
if( pos == strBuf.npos ) break;
|
|
|
|
size_t offset = ::strlen(s_vFilterList[i].strFilter.c_str());
|
|
if( offset > 1 ) strBuf.erase( pos, offset );
|
|
}
|
|
}
|
|
}
|
|
|
|
void KTextEmoticonRender::SetSprName( const char * pSprName )
|
|
{
|
|
s_strSprName = pSprName;
|
|
}
|
|
|
|
void KTextEmoticonRender::AddFilter( const char * pFilter, const char * pAniName )
|
|
{
|
|
assert( strlen(pFilter)>0 && "Filter Name Invalid Length" );
|
|
assert( strlen(pAniName)>0 && "Ani Name Invalid Length" );
|
|
|
|
EMOTICON_DATA emoticon_data;
|
|
emoticon_data.strFilter = pFilter;
|
|
emoticon_data.strAniName = pAniName;
|
|
|
|
s_vFilterList.push_back( emoticon_data );
|
|
}
|
|
|
|
void KTextEmoticonRender::ClearFilter()
|
|
{
|
|
s_vFilterList.clear();
|
|
}
|
|
|
|
bool KTextEmoticonRender::FindFilter( std::string & strText )
|
|
{
|
|
for( unsigned int i(0); s_vFilterList.size()>i; i++ )
|
|
{
|
|
size_t pos = strText.find( s_vFilterList[i].strFilter.c_str() );
|
|
|
|
if( pos != strText.npos )
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// 2010.05.06 - prodongi
|
|
void KTextEmoticonRender::modifyEmoticonSize(std::string const& aniName, int width, int height)
|
|
{
|
|
std::vector<KTextEmoticon*>::iterator it = m_vecEmoticonList.begin();
|
|
for (; it != m_vecEmoticonList.end(); ++it)
|
|
{
|
|
(*it)->setSize(aniName, width, height);
|
|
}
|
|
}
|