1586 lines
43 KiB
C++
1586 lines
43 KiB
C++
// KTextPhrase.cpp: implementation of the KTextPhrase class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "KTextPhrase.h"
|
|
#include "KTextParser.h"
|
|
#include "KRenderObject.h"
|
|
#include <toolkit/XStringUtil.h>
|
|
|
|
//#include "SDebug_Util.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef max
|
|
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
|
#endif
|
|
|
|
KTextPhrase::KTextPhrase()
|
|
: m_vPosition(0,0,KRENDER_LAYER_DEFAULT), m_fVisibility(1.0f), m_dwWidth(0), m_dwHeight(0),
|
|
m_dwLineGap(KDEFAULT_LINE_GAP), m_nYAlignPos(0), m_fFirstLine(0), m_bCaretEnable(false), m_dwMaxLine(256),
|
|
m_bReverseRendering(false), m_pTextParser(NULL), m_pCaretRender(NULL), m_bStaticSize(false)
|
|
{
|
|
m_nCaretPos = -1;
|
|
m_bCaptionRandomColor = false;
|
|
|
|
#ifdef _COUNTRY_ME_
|
|
m_bEllipsize = false;
|
|
#endif
|
|
}
|
|
KTextPhrase::KTextPhrase(DWORD dwWidth, DWORD dwHeight, DWORD dwLineGap, bool bStaticSize )
|
|
: m_vPosition(0,0,KRENDER_LAYER_DEFAULT), m_fVisibility(1.0f), m_dwWidth(dwWidth), m_dwHeight(dwHeight),
|
|
m_dwLineGap(dwLineGap), m_nYAlignPos(0), m_fFirstLine(0), m_bCaretEnable(false), m_dwMaxLine(256),
|
|
m_bReverseRendering(false), m_pTextParser(NULL), m_pCaretRender(NULL), m_bStaticSize(bStaticSize)
|
|
{
|
|
Initialize(m_dwWidth, m_dwHeight, m_dwLineGap);
|
|
m_sizeTexture.cx = 0;
|
|
m_sizeTexture.cy = 0;
|
|
|
|
m_bCaptionRandomColor = false;
|
|
|
|
#ifdef _COUNTRY_ME_
|
|
m_bEllipsize = false;
|
|
#endif
|
|
}
|
|
|
|
KTextPhrase::~KTextPhrase()
|
|
{
|
|
Clear();
|
|
SAFE_DELETE(m_pTextParser);
|
|
SAFE_DELETE(m_pCaretRender);
|
|
}
|
|
|
|
void KTextPhrase::Initialize(DWORD dwWidth, DWORD dwHeight, DWORD dwLineGap)
|
|
{
|
|
m_dwWidth = dwWidth;
|
|
m_dwHeight = dwHeight;
|
|
m_dwLineGap = dwLineGap;
|
|
|
|
SAFE_DELETE( m_pTextParser );
|
|
SAFE_DELETE( m_pCaretRender );
|
|
|
|
m_pTextParser = new KTextParser; // [MEMORY_LEAK] 2012. 3. 2 - marine 메모리 해제해줌..
|
|
|
|
DWORD dwCaretWidth = 10;
|
|
DWORD dwCaretHeight = 20;
|
|
|
|
#ifdef _COUNTRY_ME_
|
|
m_dwAlign = KTextParagraph::KTALIGN_HCENTER | KTextParagraph::KTALIGN_VCENTER;
|
|
#else
|
|
m_pCaretRender = new KTextRender(" ", 0xFF000000, KTextRender::KDEFAULT_FONT_NAME, KTextRender::KDEFAULT_FONT_SIZE, dwCaretWidth, dwCaretHeight,
|
|
KTextRender::KTALIGN_LEFT, KTextRender::KTFLAG_INVERSE, m_bStaticSize, KColor( 0xFFCDCDCD ) ); // [MEMORY_LEAK] 2012. 3. 2 - marine 메모리 해제해줌..
|
|
|
|
m_dwAlign = KTextRender::KTALIGN_HCENTER | KTextRender::KTALIGN_VCENTER;
|
|
#endif
|
|
|
|
if(m_dwWidth == 0 || m_dwHeight == 0)
|
|
{
|
|
{ assert(false && "Text Pharse's Widht or Height is 0"); }
|
|
}
|
|
|
|
}
|
|
|
|
void KTextPhrase::SetCaptionRandomColor( bool bFlag )
|
|
{
|
|
m_bCaptionRandomColor = bFlag;
|
|
}
|
|
|
|
void KTextPhrase::Clear()
|
|
{
|
|
SAFE_DELETE_VECTOR(m_vtLineList);
|
|
}
|
|
|
|
KSize KTextPhrase::GetStringSize(LPCSTR lpszString, DWORD dwDefaultWidth, DWORD dwLineGap)
|
|
{
|
|
// 2010.08.26 - prodongi
|
|
DWORD totalWidth, totalHeight, longestWidth;
|
|
calculStringSize(lpszString, dwDefaultWidth, totalWidth, totalHeight, longestWidth, dwLineGap);
|
|
#ifdef _COUNTRY_ME_
|
|
return KSize(totalWidth, totalHeight );
|
|
#else
|
|
return KSize(totalWidth, totalHeight - dwLineGap );
|
|
#endif
|
|
/*
|
|
#ifdef _COUNTRY_ME_
|
|
KTextParser parser;
|
|
parser.AddString( lpszString, 1024 );
|
|
|
|
// 2010.07.26 - prodongi
|
|
DWORD dwTotalWidth = 0;
|
|
DWORD dwWidthMax = 0, dwTotalHeight = 0;
|
|
KSize size;
|
|
|
|
for ( int i = 0; i < parser.GetParagraphCount(); ++i )
|
|
{
|
|
KTextParagraph* pPara = parser.GetTextParagraph( i );
|
|
|
|
//KTextLayout layout( dwDefaultWidth );
|
|
//KSize size = layout.GetLayoutSize( pPara );
|
|
|
|
KSize size = KTextLayout2::GetLayoutSize( pPara, dwDefaultWidth );
|
|
|
|
dwWidthMax = max( size.width, dwWidthMax );
|
|
dwTotalHeight += size.height;
|
|
// 2010.07.26 - prodongi
|
|
dwTotalWidth += size.width;
|
|
}
|
|
// 2010.07.26 - prodongi
|
|
//return KSize( dwWidthMax, dwTotalHeight );
|
|
return KSize( dwTotalWidth, dwTotalHeight );
|
|
#else
|
|
DWORD dwLongestWidth = 0;
|
|
|
|
KTextParser parser;
|
|
parser.AddString( lpszString, dwDefaultWidth );
|
|
|
|
int nPrimitiveCount = parser.GetPrimitiveCount();
|
|
DWORD dwHeight = 0, dwWidth = 0;
|
|
|
|
// 2010.07.26 - prodongi
|
|
DWORD dwTotalLineWidth = 0;
|
|
DWORD dwTotalLineHeight = 0;
|
|
int nTotalLineCount = 0;
|
|
DWORD dwOldLineWidth = 0;
|
|
for(int i = 0; i < nPrimitiveCount; ++i)
|
|
{
|
|
const KTextParser::TEXT_PRIMITIVE &textPr = parser.GetPrimitive(i);
|
|
BOOL bBold = textPr.dwFontFlag & KTextRender::KTFLAG_BOLD;
|
|
BOOL bUnder = textPr.dwFontFlag & KTextRender::KTFLAG_UNDER;
|
|
BOOL bShadow = textPr.dwFontFlag & KTextRender::KTFLAG_SHADOW;
|
|
BOOL bOutline = textPr.dwFontFlag & KTextRender::KTFLAG_OUTLINE;
|
|
BOOL bGlow = textPr.dwFontFlag & KTextRender::KTFLAG_GLOW;
|
|
|
|
if(textPr.sText.size() > 0)
|
|
{
|
|
DWORD dwStringWidth, dwStringHeight;
|
|
if( textPr.sFontName.length() )
|
|
{
|
|
KTextRender::GetStringSize(textPr.sFontName.c_str(), textPr.nFontSize, bBold, textPr.sText.c_str(), int( textPr.sText.size() ),
|
|
&dwStringWidth, &dwStringHeight);
|
|
}
|
|
else
|
|
{
|
|
KTextRender::GetStringSize("default", textPr.nFontSize, bBold, textPr.sText.c_str(), int( textPr.sText.size() ),
|
|
&dwStringWidth, &dwStringHeight);
|
|
}
|
|
|
|
|
|
dwStringHeight += dwLineGap;
|
|
if(bUnder) dwStringHeight++;
|
|
|
|
if( bShadow ) dwStringWidth += 1;
|
|
if( bOutline ) dwStringWidth += 2;
|
|
if( bGlow ) dwStringWidth += 4;
|
|
|
|
// 옵셋 관련
|
|
if( textPr.dwOffset )
|
|
{
|
|
// 2010.07.28 - prodongi
|
|
dwWidth += dwStringWidth;
|
|
|
|
DWORD dwCurWidth = textPr.dwOffset + dwStringWidth;
|
|
dwWidth = max( dwWidth, dwCurWidth );
|
|
}
|
|
else
|
|
{
|
|
dwWidth += dwStringWidth;
|
|
}
|
|
|
|
dwHeight = max(dwHeight, dwStringHeight) + (bShadow?1:0) + (bOutline?2:0) + (bGlow?4:0);
|
|
}
|
|
|
|
else if(textPr.dwIconType == KTextParser::KICON_EMOTICON || textPr.dwIconType == KTextParser::KICON_NX3)
|
|
{
|
|
dwHeight = max(dwHeight, textPr.nFontSize * 2);
|
|
//Icon은 따로 Icon Layer를 만들어 줘서 해야 하겠지..
|
|
//현재 버전에서는 우선은 지원하지 말자
|
|
//(알파 이후로 지원 예정 -_-)
|
|
}
|
|
|
|
// 다음줄로 넘어가자
|
|
if(textPr.nBreak != 0 || textPr.nPageBreak != 0 || textPr.bIsLineBreak || i == nPrimitiveCount -1)
|
|
{
|
|
|
|
if(dwHeight == 0)
|
|
{
|
|
dwHeight = KTextRender::GetFontHeight( textPr.nFontSize );
|
|
}
|
|
|
|
nTotalLineCount++;
|
|
dwTotalLineHeight += dwHeight;
|
|
dwHeight = 0;
|
|
|
|
// 2010.07.26 - prodongi
|
|
dwTotalLineWidth += dwWidth;
|
|
|
|
dwLongestWidth = max(dwLongestWidth, dwWidth );
|
|
dwWidth = 0;
|
|
}
|
|
}
|
|
|
|
// 2010.07.26 - prodongi
|
|
//KSize size(dwLongestWidth, dwTotalLineHeight - dwLineGap );
|
|
KSize size(dwTotalLineWidth, dwTotalLineHeight - dwLineGap );
|
|
return size;
|
|
#endif
|
|
*/
|
|
}
|
|
|
|
// 2010.08.26 - prodongi
|
|
KSize KTextPhrase::GetLongestStringSize(LPCSTR lpszString, DWORD dwDefaultWidth, DWORD dwLineGap)
|
|
{
|
|
// 2010.08.26 - prodongi
|
|
DWORD totalWidth, totalHeight, longestWidth;
|
|
calculStringSize(lpszString, dwDefaultWidth, totalWidth, totalHeight, longestWidth, dwLineGap);
|
|
#ifdef _COUNTRY_ME_
|
|
return KSize(longestWidth, totalHeight );
|
|
#else
|
|
return KSize(longestWidth, totalHeight - dwLineGap );
|
|
#endif
|
|
}
|
|
|
|
|
|
// 2010.08.26 - prodongi
|
|
void KTextPhrase::calculStringSize(LPCSTR lpszString, DWORD dwDefaultWidth, DWORD& totalWidth, DWORD& totalHeight, DWORD& longestWidth, DWORD dwLineGap)
|
|
{
|
|
#ifdef _COUNTRY_ME_
|
|
KTextParser parser;
|
|
parser.AddString( lpszString, 1024 );
|
|
|
|
// 2010.07.26 - prodongi
|
|
DWORD dwTotalWidth = 0;
|
|
DWORD dwWidthMax = 0, dwTotalHeight = 0;
|
|
KSize size;
|
|
|
|
for ( int i = 0; i < parser.GetParagraphCount(); ++i )
|
|
{
|
|
KTextParagraph* pPara = parser.GetTextParagraph( i );
|
|
|
|
/*
|
|
KTextLayout layout( dwDefaultWidth );
|
|
KSize size = layout.GetLayoutSize( pPara );
|
|
*/
|
|
KSize size = KTextLayout2::GetLayoutSize( pPara, dwDefaultWidth );
|
|
|
|
dwWidthMax = max( size.width, dwWidthMax );
|
|
dwTotalHeight += size.height;
|
|
// 2010.07.26 - prodongi
|
|
dwTotalWidth += size.width;
|
|
}
|
|
// 2010.07.26 - prodongi
|
|
//return KSize( dwWidthMax, dwTotalHeight );
|
|
//return KSize( dwTotalWidth, dwTotalHeight );
|
|
totalWidth = dwTotalWidth;
|
|
totalHeight = dwTotalHeight;
|
|
longestWidth = dwWidthMax;
|
|
#else
|
|
DWORD dwLongestWidth = 0;
|
|
|
|
KTextParser parser;
|
|
parser.AddString( lpszString, dwDefaultWidth );
|
|
|
|
int nPrimitiveCount = parser.GetPrimitiveCount();
|
|
DWORD dwHeight = 0, dwWidth = 0;
|
|
|
|
// 2010.07.26 - prodongi
|
|
DWORD dwTotalLineWidth = 0;
|
|
DWORD dwTotalLineHeight = 0;
|
|
int nTotalLineCount = 0;
|
|
DWORD dwOldLineWidth = 0;
|
|
for(int i = 0; i < nPrimitiveCount; ++i)
|
|
{
|
|
const KTextParser::TEXT_PRIMITIVE &textPr = parser.GetPrimitive(i);
|
|
BOOL bBold = textPr.dwFontFlag & KTextRender::KTFLAG_BOLD;
|
|
BOOL bUnder = textPr.dwFontFlag & KTextRender::KTFLAG_UNDER;
|
|
BOOL bShadow = textPr.dwFontFlag & KTextRender::KTFLAG_SHADOW;
|
|
BOOL bOutline = textPr.dwFontFlag & KTextRender::KTFLAG_OUTLINE;
|
|
BOOL bGlow = textPr.dwFontFlag & KTextRender::KTFLAG_GLOW;
|
|
|
|
if(textPr.sText.size() > 0)
|
|
{
|
|
DWORD dwStringWidth, dwStringHeight;
|
|
if( textPr.sFontName.length() )
|
|
{
|
|
KTextRender::GetStringSize(textPr.sFontName.c_str(), textPr.nFontSize, bBold, textPr.sText.c_str(), int( textPr.sText.size() ),
|
|
&dwStringWidth, &dwStringHeight);
|
|
}
|
|
else
|
|
{
|
|
KTextRender::GetStringSize("default", textPr.nFontSize, bBold, textPr.sText.c_str(), int( textPr.sText.size() ),
|
|
&dwStringWidth, &dwStringHeight);
|
|
}
|
|
|
|
|
|
dwStringHeight += dwLineGap;
|
|
if(bUnder) dwStringHeight++;
|
|
|
|
if( bShadow ) dwStringWidth += 1;
|
|
if( bOutline ) dwStringWidth += 2;
|
|
if( bGlow ) dwStringWidth += 4;
|
|
|
|
// 옵셋 관련
|
|
if( textPr.dwOffset )
|
|
{
|
|
// 2010.07.28 - prodongi
|
|
dwWidth += dwStringWidth;
|
|
|
|
DWORD dwCurWidth = textPr.dwOffset + dwStringWidth;
|
|
dwWidth = max( dwWidth, dwCurWidth );
|
|
}
|
|
else
|
|
{
|
|
dwWidth += dwStringWidth;
|
|
}
|
|
|
|
dwHeight = max(dwHeight, dwStringHeight) + (bShadow?1:0) + (bOutline?2:0) + (bGlow?4:0);
|
|
}
|
|
|
|
else if(textPr.dwIconType == KTextParser::KICON_EMOTICON || textPr.dwIconType == KTextParser::KICON_NX3)
|
|
{
|
|
dwHeight = max(dwHeight, textPr.nFontSize * 2);
|
|
//Icon은 따로 Icon Layer를 만들어 줘서 해야 하겠지..
|
|
//현재 버전에서는 우선은 지원하지 말자
|
|
//(알파 이후로 지원 예정 -_-)
|
|
}
|
|
|
|
// 다음줄로 넘어가자
|
|
if(textPr.nBreak != 0 || textPr.nPageBreak != 0 || textPr.bIsLineBreak || i == nPrimitiveCount -1)
|
|
{
|
|
|
|
if(dwHeight == 0)
|
|
{
|
|
dwHeight = KTextRender::GetFontHeight( textPr.nFontSize );
|
|
}
|
|
|
|
nTotalLineCount++;
|
|
dwTotalLineHeight += dwHeight;
|
|
dwHeight = 0;
|
|
|
|
// 2010.07.26 - prodongi
|
|
dwTotalLineWidth += dwWidth;
|
|
|
|
dwLongestWidth = max(dwLongestWidth, dwWidth );
|
|
dwWidth = 0;
|
|
}
|
|
}
|
|
|
|
// 2010.07.26 - prodongi
|
|
//KSize size(dwLongestWidth, dwTotalLineHeight - dwLineGap );
|
|
KSize size(dwTotalLineWidth, dwTotalLineHeight - dwLineGap );
|
|
//return size;
|
|
totalWidth = dwTotalLineWidth;
|
|
totalHeight = dwTotalLineHeight;
|
|
longestWidth = dwLongestWidth;
|
|
#endif
|
|
}
|
|
|
|
void KTextPhrase::GetSplitString(LPCSTR lpszString, DWORD dwDefaultWidth, std::vector<std::string>& splitList, bool bUseFontSize /*= false*/ )
|
|
{
|
|
#ifdef _COUNTRY_ME_
|
|
DWORD dwLongestWidth = 0;
|
|
|
|
KTextParser parser;
|
|
parser.AddString( lpszString, dwDefaultWidth, true, true );
|
|
|
|
KTextParagraph* pPara;
|
|
|
|
int nParaCount = parser.GetParagraphCount();
|
|
for ( int i = 0; i < nParaCount; ++i )
|
|
{
|
|
pPara = parser.GetTextParagraph( i );
|
|
splitList.push_back( pPara->GetMultibyteString() );
|
|
}
|
|
#else
|
|
DWORD dwLongestWidth = 0;
|
|
|
|
KTextParser parser;
|
|
parser.AddString( lpszString, dwDefaultWidth, true, true, false );
|
|
|
|
int nPrimitiveCount = parser.GetPrimitiveCount();
|
|
DWORD dwHeight = 0, dwWidth = 0;
|
|
|
|
DWORD dwTotalLineHeight = 0;
|
|
int nTotalLineCount = 0;
|
|
DWORD dwOldLineWidth = 0;
|
|
|
|
std::string strLine;
|
|
|
|
for(int i = 0; i < nPrimitiveCount; ++i)
|
|
{
|
|
const KTextParser::TEXT_PRIMITIVE &textPr = parser.GetPrimitive(i);
|
|
|
|
std::string strParser = textPr.sText;
|
|
|
|
if( bUseFontSize )
|
|
AttachFontSizeAndColor( strParser, textPr.nFontSize, textPr.Color );
|
|
|
|
if( textPr.dwOffset > 0 )
|
|
AttachOffSet( strParser, textPr.dwOffset );
|
|
|
|
|
|
ConvertTag(strParser, textPr.dwFontFlag);
|
|
|
|
strLine += strParser;
|
|
if( !strLine.empty() && textPr.bIsLineBreak )
|
|
{
|
|
splitList.push_back( strLine );
|
|
strLine.clear();
|
|
}
|
|
}
|
|
if( !strLine.empty() )
|
|
{
|
|
splitList.push_back( strLine );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void KTextPhrase::ConvertTag( std::string& rOutText, DWORD dwFlag )
|
|
{
|
|
BOOL bUnder = dwFlag & KTextRender::KTFLAG_UNDER;
|
|
BOOL bStrike = dwFlag & KTextRender::KTFLAG_STRIKE;
|
|
BOOL bInverse = dwFlag & KTextRender::KTFLAG_INVERSE;
|
|
BOOL bBold = dwFlag & KTextRender::KTFLAG_BOLD;
|
|
BOOL bShadow = dwFlag & KTextRender::KTFLAG_SHADOW;
|
|
BOOL bOutline = dwFlag & KTextRender::KTFLAG_OUTLINE;
|
|
BOOL bGlow = dwFlag & KTextRender::KTFLAG_GLOW;
|
|
BOOL bGlow2X = dwFlag & KTextRender::KTFLAG_GLOW2X;
|
|
|
|
if( bUnder ) AttachTag(rOutText, "<U>" , "</U>" );
|
|
if( bStrike ) AttachTag(rOutText, "<STRIKE>", "</STRIKE>" );
|
|
if( bInverse ) AttachTag(rOutText, "<INV>" , "</INV>" );
|
|
if( bBold ) AttachTag(rOutText, "<B>" , "</B>" );
|
|
if( bShadow ) AttachTag(rOutText, "<SHADOW>", "</SHADOW>" );
|
|
if( bOutline ) AttachTag(rOutText, "<OUT>" , "</OUT>" );
|
|
if( bGlow ) AttachTag(rOutText, "<GLOW>" , "</GLOW>" );
|
|
if( bGlow2X ) AttachTag(rOutText, "<2XGLOW>", "</2XGLOW>" );
|
|
}
|
|
|
|
void KTextPhrase::AttachTag( std::string& rOutText, const char* lpStartTag, const char* lpEndTag )
|
|
{
|
|
std::string strTemp = lpStartTag + rOutText;
|
|
rOutText = strTemp + lpEndTag;
|
|
}
|
|
|
|
std::string strFormat( const char* szString, ... )
|
|
{
|
|
char szBuf[1024]={0,};
|
|
|
|
va_list va;
|
|
va_start( va, szString );
|
|
_vsnprintf( szBuf, _countof(szBuf), szString, va );
|
|
va_end( va );
|
|
|
|
return std::string( szBuf );
|
|
}
|
|
|
|
void KTextPhrase::AttachFontSizeAndColor( std::string& rOutText, const int& nSize, const KColor& color )
|
|
{
|
|
std::string strTemp = strFormat( "<#%02x%02x%02x><size:%d>%s", color.r, color.g, color.b, nSize, rOutText.c_str() );
|
|
rOutText = strTemp;
|
|
}
|
|
|
|
void KTextPhrase::AttachOffSet( std::string& rOutText, const DWORD& nOffSet )
|
|
{
|
|
std::string strTemp = strFormat( "<OFFSET:%d>%s", nOffSet, rOutText.c_str() );
|
|
rOutText = strTemp;
|
|
}
|
|
|
|
DWORD KTextPhrase::GetOneLineStringSize(LPCSTR lpszString, DWORD* pWidth, DWORD* pHeight)
|
|
{
|
|
#ifdef _COUNTRY_ME_
|
|
KTextParser parser;
|
|
/// 2011.05.09 redmine #7 - prodongi
|
|
parser.AddString( lpszString, -1 );
|
|
//parser.AddString( lpszString, pWidth ? (*pWidth) : -1 );
|
|
|
|
DWORD dwWidthMax = 0, dwHeightMax = 0;
|
|
KSize size;
|
|
|
|
for ( int i = 0; i < parser.GetParagraphCount(); ++i )
|
|
{
|
|
KTextParagraph* pPara = parser.GetTextParagraph( i );
|
|
/*
|
|
KTextLayout layout( -1 );
|
|
|
|
size = layout.GetLayoutSize( pPara );
|
|
*/
|
|
/// 2011.05.09 redmine #7 - prodongi
|
|
size = KTextLayout2::GetLayoutSize( pPara, -1 );
|
|
//size = KTextLayout2::GetLayoutSize( pPara, pWidth ? (*pWidth) : -1 );
|
|
|
|
if ( pPara->GetOffsetX() )
|
|
dwWidthMax = max( size.width + pPara->GetOffsetX(), dwWidthMax );
|
|
else
|
|
dwWidthMax += size.width;
|
|
|
|
dwHeightMax = max( size.height, dwHeightMax );
|
|
}
|
|
if ( pWidth != NULL )
|
|
*pWidth = dwWidthMax;
|
|
if ( pHeight != NULL )
|
|
*pHeight = dwHeightMax;
|
|
return dwWidthMax;
|
|
#else
|
|
KTextParser parser;
|
|
parser.AddString(lpszString,1024);
|
|
|
|
int nPrimitiveCount = parser.GetPrimitiveCount();
|
|
|
|
DWORD dwWidth = 0, dwHeight = 0;
|
|
DWORD dwPrWidth = 0, dwPrHeight = 0;
|
|
|
|
for(int i = 0; i < nPrimitiveCount; ++i)
|
|
{
|
|
const KTextParser::TEXT_PRIMITIVE &textPr = parser.GetPrimitive(i);
|
|
BOOL bBold = textPr.dwFontFlag & KTextRender::KTFLAG_BOLD;
|
|
BOOL bUnder = textPr.dwFontFlag & KTextRender::KTFLAG_UNDER;
|
|
BOOL bShadow = textPr.dwFontFlag & KTextRender::KTFLAG_SHADOW;
|
|
BOOL bOutline = textPr.dwFontFlag & KTextRender::KTFLAG_OUTLINE;
|
|
BOOL bGlow = textPr.dwFontFlag & KTextRender::KTFLAG_GLOW;
|
|
if(textPr.sText.size() > 0)
|
|
{
|
|
if( textPr.sFontName.length() )
|
|
{
|
|
KTextRender::GetStringSize(textPr.sFontName.c_str(), textPr.nFontSize, bBold, textPr.sText.c_str(), int( textPr.sText.size() ),
|
|
&dwPrWidth, &dwPrHeight);
|
|
}
|
|
else
|
|
{
|
|
KTextRender::GetStringSize("default", textPr.nFontSize, bBold, textPr.sText.c_str(), int( textPr.sText.size() ),
|
|
&dwPrWidth, &dwPrHeight);
|
|
}
|
|
|
|
if(bUnder) dwPrHeight++;
|
|
|
|
if( bShadow ) dwPrWidth += 1;
|
|
if( bOutline ) dwPrWidth += 2;
|
|
if( bGlow ) dwPrWidth += 4;
|
|
|
|
// 옵셋 관련
|
|
if( textPr.dwOffset )
|
|
{
|
|
DWORD dwCurWidth = textPr.dwOffset + dwPrWidth;
|
|
dwWidth = max( dwWidth, dwCurWidth );
|
|
}
|
|
else
|
|
{
|
|
dwWidth += dwPrWidth;
|
|
}
|
|
|
|
dwHeight = max(dwHeight, dwPrHeight) + (bShadow?1:0) + (bOutline?2:0) + (bGlow?4:0);
|
|
}
|
|
}
|
|
|
|
if(NULL != pWidth )
|
|
{
|
|
*pWidth = dwWidth;
|
|
}
|
|
|
|
if(NULL != pHeight)
|
|
{
|
|
*pHeight = dwHeight;
|
|
}
|
|
|
|
return dwWidth;
|
|
#endif
|
|
}
|
|
|
|
void KTextPhrase::SetEditMode( bool bFlag )
|
|
{
|
|
if( m_pTextParser ) m_pTextParser->SetEditMode( bFlag );
|
|
}
|
|
|
|
#ifdef _COUNTRY_ME_
|
|
|
|
// 2010.09.03 - prodongi
|
|
void KTextPhrase::AddString(LPCSTR lpszString, float fZPos/*0.0f*/, bool bTagEnable, bool bStaticSize, bool bUseEmoticonFilter, bool scroll, DWORD maxWidth )
|
|
//void KTextPhrase::AddString(LPCSTR lpszString, float fZPos/*0.0f*/, bool bTagEnable, bool bStaticSize, bool bUseEmoticonFilter )
|
|
{
|
|
if( !m_pTextParser )
|
|
{
|
|
assert( false && "KTextPhrase::AddString m_pTextParser == NULL" );
|
|
return;
|
|
}
|
|
|
|
DWORD dwHeight = 0;
|
|
|
|
m_bStaticSize = bStaticSize;
|
|
|
|
// 생성할때 설정한 넓이로 Parsing한다.
|
|
DWORD dwHALign = ( KTextParagraph::KTALIGN_LEFT & m_dwAlign ) | (KTextParagraph::KTALIGN_HCENTER & m_dwAlign);
|
|
DWORD dwVALign = ( KTextParagraph::KTALIGN_BOTTOM & m_dwAlign ) | (KTextParagraph::KTALIGN_VCENTER & m_dwAlign);
|
|
|
|
m_pTextParser->SetAlign(dwHALign,dwVALign);
|
|
// 2010.06.08 - prodongi
|
|
// 2010.09.03 - prodongi
|
|
DWORD _maxWidth = (maxWidth) ? maxWidth : m_dwWidth;
|
|
m_pTextParser->AddString( lpszString, _maxWidth/*m_dwWidth*/, bTagEnable, false, scroll );
|
|
//m_pTextParser->AddString( lpszString, m_dwWidth, bTagEnable );
|
|
|
|
m_dwAlign = m_pTextParser->GetAlign();
|
|
|
|
int nPrimitiveCount = m_pTextParser->GetParagraphCount();
|
|
|
|
KTEXT_LINE_OBJECT * pLineObject;
|
|
|
|
KRect rcRect(m_vPosition.x, m_vPosition.y, m_vPosition.x + m_dwWidth, m_vPosition.y + m_dwHeight);
|
|
|
|
pLineObject = new KTEXT_LINE_OBJECT;
|
|
KSize size;
|
|
DWORD dwWidthSoFar = 0;
|
|
for(int i = 0; i < nPrimitiveCount; ++i)
|
|
{
|
|
KTextParagraph* pPara = m_pTextParser->GetTextParagraph(i);
|
|
|
|
if ( pPara->m_bEmoticon )
|
|
{
|
|
KTextEmoticon* pEmoticon = new KTextEmoticon( KTextEmoticon::TYPE_NORMAL, 0, 0, 0, 0, pPara->m_strText.c_str(), "ui_frame.spr", fZPos );
|
|
pEmoticon->Initialize( false );
|
|
|
|
KTEXT_OBJECT object;
|
|
object.pEmoticonRender = pEmoticon;
|
|
object.nType = 1;
|
|
if ( pPara->m_dwOffsetX )
|
|
object.dwXPos = pPara->m_dwOffsetX;
|
|
else
|
|
object.dwXPos = dwWidthSoFar;
|
|
object.dwXWidth = pEmoticon->GetWidth();
|
|
|
|
pLineObject->vtLineObject.push_back(object);
|
|
size.width = object.dwXWidth;
|
|
size.height = 0;
|
|
}
|
|
else
|
|
{
|
|
size = KTextLayout2::GetLayoutSize( pPara, m_dwWidth );
|
|
/*
|
|
KTextLayout layout( m_dwWidth, m_dwHeight, m_dwLineGap, m_dwAlign );
|
|
size = layout.GetLayoutSize( pPara );
|
|
*/
|
|
|
|
if ( pPara->GetString().length() )
|
|
{
|
|
KTextRender* pRender;
|
|
pRender = new KTextRender( pPara, size.width, size.height, m_dwLineGap, m_dwAlign, m_bCaptionRandomColor );
|
|
|
|
pRender->SetClipRect(rcRect);
|
|
|
|
KTEXT_OBJECT object;
|
|
object.pTextRender = pRender;
|
|
object.nType = 0;
|
|
if ( pPara->m_dwOffsetX )
|
|
object.dwXPos = pPara->m_dwOffsetX;
|
|
else
|
|
object.dwXPos = dwWidthSoFar;
|
|
object.dwXWidth = size.width;
|
|
|
|
pLineObject->vtLineObject.push_back(object);
|
|
}
|
|
}
|
|
dwWidthSoFar += pPara->m_dwOffsetX + size.width;
|
|
|
|
m_sizeTexture.cx = max( m_sizeTexture.cx, dwWidthSoFar );
|
|
pLineObject->dwLineWidth = max( dwWidthSoFar, pLineObject->dwLineWidth );
|
|
pLineObject->dwLineHeight = max( size.height, pLineObject->dwLineHeight );
|
|
|
|
if ( pPara->GetLineBreak() )
|
|
{
|
|
m_vtLineList.push_back( pLineObject );
|
|
m_sizeTexture.cy += pLineObject->dwLineHeight + m_dwLineGap;
|
|
pLineObject = new KTEXT_LINE_OBJECT;
|
|
dwWidthSoFar = 0;
|
|
}
|
|
}
|
|
if ( !pLineObject->vtLineObject.empty() )
|
|
{
|
|
m_vtLineList.push_back( pLineObject );
|
|
m_sizeTexture.cy += pLineObject->dwLineHeight;
|
|
}
|
|
else
|
|
delete pLineObject;
|
|
|
|
|
|
// Delete over maxline object.
|
|
if(m_vtLineList.size() > m_dwMaxLine)
|
|
{
|
|
int nDeleteSize = int(m_vtLineList.size()) - int(m_dwMaxLine);
|
|
for(int i = 0; i < nDeleteSize; ++i)
|
|
{
|
|
SAFE_DELETE(m_vtLineList.front());
|
|
|
|
// always delete head
|
|
m_vtLineList.erase(m_vtLineList.begin() );
|
|
}
|
|
}
|
|
m_pTextParser->Clear();
|
|
// 이제 Align을 맞춰주자
|
|
SetAlign(m_dwAlign);
|
|
}
|
|
#else
|
|
// 2010.09.03 - prodongi
|
|
void KTextPhrase::AddString(LPCSTR lpszString, float fZPos/*0.0f*/, bool bTagEnable, bool bStaticSize, bool bUseEmoticonFilter, bool scroll, DWORD maxWidth )
|
|
//void KTextPhrase::AddString(LPCSTR lpszString, float fZPos/*0.0f*/, bool bTagEnable, bool bStaticSize, bool bUseEmoticonFilter )
|
|
{
|
|
if( !m_pTextParser )
|
|
{
|
|
assert( false && "KTextPhrase::AddString m_pTextParser == NULL" );
|
|
return;
|
|
}
|
|
|
|
DWORD dwHeight = 0;
|
|
|
|
m_bStaticSize = bStaticSize;
|
|
|
|
// 생성할때 설정한 넓이로 Parsing한다.
|
|
DWORD dwHALign = ( KTextRender::KTALIGN_RIGHT & m_dwAlign ) | (KTextRender::KTALIGN_HCENTER & m_dwAlign);
|
|
DWORD dwVALign = ( KTextRender::KTALIGN_BOTTOM & m_dwAlign ) | (KTextRender::KTALIGN_VCENTER & m_dwAlign);
|
|
|
|
m_pTextParser->SetAlign(dwHALign,dwVALign);
|
|
// 2010.06.08 - prodongi
|
|
// 2010.09.03 - prodongi
|
|
DWORD _maxWidth = (maxWidth) ? maxWidth : m_dwWidth;
|
|
m_pTextParser->AddString( lpszString, _maxWidth/*m_dwWidth*/, bTagEnable, false, scroll );
|
|
//m_pTextParser->AddString( lpszString, m_dwWidth, bTagEnable );
|
|
|
|
m_dwAlign = m_pTextParser->GetAlign();
|
|
|
|
int nPrimitiveCount = m_pTextParser->GetPrimitiveCount();
|
|
|
|
KTEXT_LINE_OBJECT * pLineObject = new KTEXT_LINE_OBJECT;
|
|
DWORD dwXCorrPos = 0;
|
|
|
|
KRect rcRect(m_vPosition.x, m_vPosition.y, m_vPosition.x + m_dwWidth, m_vPosition.y + m_dwHeight);
|
|
|
|
for(int i = 0; i < nPrimitiveCount; ++i)
|
|
{
|
|
const KTextParser::TEXT_PRIMITIVE &textPr = m_pTextParser->GetPrimitive(i);
|
|
BOOL bBold = textPr.dwFontFlag & KTextRender::KTFLAG_BOLD;
|
|
BOOL bUnder = textPr.dwFontFlag & KTextRender::KTFLAG_UNDER;
|
|
BOOL bShadow = textPr.dwFontFlag & KTextRender::KTFLAG_SHADOW;
|
|
BOOL bOutline = textPr.dwFontFlag & KTextRender::KTFLAG_OUTLINE;
|
|
BOOL bGlow = textPr.dwFontFlag & KTextRender::KTFLAG_GLOW;
|
|
|
|
// Text를 찍는 경우
|
|
if(textPr.sText.size() > 0)
|
|
{
|
|
//if( textPr.sText == "호호호" || textPr.sText == "ㅋㅋㅋ" )
|
|
//{
|
|
// int k = 3;
|
|
//}
|
|
|
|
DWORD dwStringWidth, dwStringHeight;
|
|
if( textPr.sFontName.length() )
|
|
{
|
|
KTextRender::GetStringSize(textPr.sFontName.c_str(), textPr.nFontSize, bBold, textPr.sText.c_str(), int( textPr.sText.size() ),
|
|
&dwStringWidth, &dwStringHeight);
|
|
}
|
|
else
|
|
{
|
|
KTextRender::GetStringSize("default", textPr.nFontSize, bBold, textPr.sText.c_str(), int( textPr.sText.size() ),
|
|
&dwStringWidth, &dwStringHeight);
|
|
}
|
|
|
|
bool isTexSpriteScroll = false;
|
|
/// 2011.02.23 스크롤이 될때는 텍스춰 길이가 최소한 컨트롤 길이 만큼 되야 된다 - prodongi
|
|
if (0 == i && m_spriteScrollInfo.m_scroll)
|
|
{
|
|
if (dwStringWidth < _maxWidth)
|
|
{
|
|
dwStringWidth = _maxWidth;
|
|
isTexSpriteScroll = true;
|
|
}
|
|
}
|
|
|
|
// 아래 부분 수정이 필요함 ( Parser 에서 Width 나 Height값을 보정하도록)
|
|
dwStringHeight += m_dwLineGap + (bShadow?1:0) + (bOutline?2:0) + (bGlow?4:0);
|
|
if(bUnder)
|
|
dwStringHeight += 2;
|
|
dwStringWidth += (bShadow?1:0) + (bOutline?2:0) + (bGlow?4:0);
|
|
|
|
dwHeight = max(dwHeight, dwStringHeight);
|
|
|
|
KTextRender* pRender = NULL;
|
|
|
|
/// 2011.02.23 isTexSpriteScroll 추가 - prodongi
|
|
pRender = new KTextRender(textPr.sText.c_str(), textPr.Color.color,
|
|
textPr.sFontName.c_str(), textPr.nFontSize, dwStringWidth, dwStringHeight,
|
|
KTextRender::KTALIGN_LEFT | KTextRender::KTALIGN_TOP, textPr.dwFontFlag, m_bStaticSize, textPr.ColorFX, fZPos, m_bCaptionRandomColor, bUseEmoticonFilter, isTexSpriteScroll );
|
|
|
|
pRender->SetClipRect(rcRect);
|
|
|
|
// MIMI 2005/08/17 이모티콘이 있을경우(height이 달라졌을경우) 글자들은 세로위치를 보정해준다.
|
|
if( dwHeight != dwStringHeight )
|
|
{
|
|
dwHeight = dwStringHeight;
|
|
// 줄간격 여백 준다.
|
|
dwHeight += 2;
|
|
}
|
|
|
|
if( textPr.dwOffset )
|
|
dwXCorrPos = textPr.dwOffset;
|
|
|
|
// MIMI 2005/08/17 가로 결정
|
|
if( ( dwXCorrPos + dwStringWidth ) > m_sizeTexture.cx )
|
|
m_sizeTexture.cx = dwStringWidth + dwXCorrPos;
|
|
|
|
KTEXT_OBJECT object;
|
|
object.pRender = pRender;
|
|
object.dwXPos = dwXCorrPos;
|
|
object.nOffsetY = textPr.nOffsetY; // 그려질 오브젝트 y 오프셋
|
|
// 2010.07.28 test - prodongi
|
|
if (KTextRender::KTALIGN_BOTTOM & m_dwAlign)
|
|
{
|
|
DWORD oriHeight = KTextRender::GetFontHeight( textPr.nFontSize ) + m_dwLineGap;
|
|
object.nOffsetY += (int)oriHeight - (int)dwHeight;
|
|
}
|
|
|
|
|
|
object.dwXWidth = dwStringWidth;
|
|
pLineObject->vtLineObject.push_back(object); // [MEMORY_LEAK] 2012. 3. 5 - marine ->object의 pRender 가 릭이라고 나오는데 스마트 포인터임..
|
|
|
|
dwXCorrPos += dwStringWidth;
|
|
}
|
|
|
|
//Icon을 찍는경우
|
|
else if(textPr.dwIconType == KTextParser::KICON_EMOTICON || textPr.dwIconType == KTextParser::KICON_NX3)
|
|
{
|
|
dwXCorrPos += textPr.nFontSize * 2;
|
|
dwHeight = max(dwHeight, textPr.nFontSize * 2);
|
|
//Icon은 따로 Icon Layer를 만들어 줘서 해야 하겠지..
|
|
//현재 버전에서는 우선은 지원하지 말자
|
|
//(알파 이후로 지원 예정 -_-)
|
|
}
|
|
|
|
|
|
// 다음줄로 넘어가자
|
|
// Line Object에 넣어주고 새로운 Line Object를 생성한다.
|
|
if(textPr.nBreak != 0 || textPr.nPageBreak != 0 || textPr.bIsLineBreak || i == nPrimitiveCount -1)
|
|
{
|
|
|
|
if(dwHeight == 0)
|
|
{
|
|
dwHeight = KTextRender::GetFontHeight( textPr.nFontSize );
|
|
}
|
|
|
|
pLineObject->dwLineWidth = dwXCorrPos;
|
|
pLineObject->dwLineHeight = dwHeight;
|
|
m_vtLineList.push_back(pLineObject);
|
|
|
|
pLineObject = NULL;
|
|
pLineObject = new KTEXT_LINE_OBJECT;
|
|
|
|
m_sizeTexture.cy += dwHeight;
|
|
|
|
// Align Value 초기화
|
|
dwXCorrPos = 0;
|
|
dwHeight = 0;
|
|
}
|
|
}
|
|
|
|
// Delete over maxline object.
|
|
if(m_vtLineList.size() > m_dwMaxLine)
|
|
{
|
|
int nDeleteSize = int(m_vtLineList.size()) - int(m_dwMaxLine);
|
|
for(int i = 0; i < nDeleteSize; ++i)
|
|
{
|
|
SAFE_DELETE(m_vtLineList.front());
|
|
|
|
// always delete head
|
|
m_vtLineList.erase(m_vtLineList.begin() );
|
|
}
|
|
}
|
|
SAFE_DELETE(pLineObject);
|
|
m_pTextParser->Clear();
|
|
// 이제 Align을 맞춰주자
|
|
SetAlign(m_dwAlign);
|
|
}
|
|
#endif
|
|
void KTextPhrase::SetPosition( float x, float y, float z)
|
|
{
|
|
m_vPosition.x = x; m_vPosition.y = y; m_vPosition.z = z;
|
|
|
|
KRect rcRect(m_vPosition.x, m_vPosition.y, m_vPosition.x + m_dwWidth, m_vPosition.y + m_dwHeight);
|
|
|
|
for(int i = 0; i < m_vtLineList.size(); ++i)
|
|
{
|
|
KTEXT_LINE_OBJECT * pLineObject = m_vtLineList.at(i);
|
|
|
|
for(int j = 0; j < pLineObject->vtLineObject.size(); ++j)
|
|
{
|
|
KTEXT_OBJECT & object = pLineObject->vtLineObject.at(j);
|
|
#ifdef _COUNTRY_ME_
|
|
if ( object.nType == 0 )
|
|
object.pTextRender->SetClipRect(rcRect);
|
|
#else
|
|
object.pRender->SetClipRect(rcRect);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
void KTextPhrase::SetAddPosition(float xAdd, float yAdd, float zAdd)
|
|
{
|
|
SetPosition(m_vPosition.x + xAdd, m_vPosition.y + yAdd,m_vPosition.z + zAdd );
|
|
}
|
|
|
|
void KTextPhrase::SetZPosition(float fZPos)
|
|
{
|
|
m_vPosition.z = fZPos;
|
|
}
|
|
|
|
DWORD KTextPhrase::GetTotalLineHeigt()
|
|
{
|
|
DWORD dwTotalHeight = 0;
|
|
for(int i = 0; i < m_vtLineList.size(); ++i)
|
|
{
|
|
dwTotalHeight += m_vtLineList.at(i)->dwLineHeight + m_dwLineGap;
|
|
}
|
|
|
|
// 마지막 한줄의 Gap은 빼준다.
|
|
return dwTotalHeight - m_dwLineGap;
|
|
}
|
|
|
|
float KTextPhrase::GetPageLineNumber()
|
|
{
|
|
// 마지막 한줄의 Gap은 빼준다.
|
|
int dwHeight = - (int)m_dwLineGap;
|
|
for(int i = int(m_vtLineList.size() - 1); i >= 0; --i)
|
|
{
|
|
dwHeight += m_vtLineList.at(i)->dwLineHeight;
|
|
// 1Page를 넘어가게 되면
|
|
if(dwHeight >= m_dwHeight)
|
|
{
|
|
float fDiff = 1.0f - ( (float)(dwHeight - m_dwHeight) / (float)m_vtLineList.at(i)->dwLineHeight );
|
|
// Indexing 체크
|
|
return (float)i + fDiff;
|
|
//return m_vtLineList.size() > i + 1 ? i + 1 : i;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
#ifndef _COUNTRY_ME_
|
|
|
|
|
|
DWORD KTextPhrase::GetOneLineStringByte(LPCSTR lpszText, DWORD dwWidth )
|
|
{
|
|
bool IsOldUseWordWrap = KTextParser::GetUseWordWrap();
|
|
|
|
KTextParser::SetUseWordWrap( false );
|
|
|
|
KTextParser parser;
|
|
parser.AddString( lpszText, dwWidth);
|
|
|
|
KTextParser::SetUseWordWrap( IsOldUseWordWrap );
|
|
|
|
if( parser.GetPrimitiveCount() <= 0)
|
|
return 0;
|
|
|
|
/// 2010.10.29 조건문에 안 결리는 경우가 있기 때문에 초기 값을 최대 카운트로 해준다 - prodongi
|
|
//int nFirstLineBreakIndex = 0;
|
|
int nFirstLineBreakIndex = parser.GetPrimitiveCount() - 1;
|
|
|
|
for(int i = 0; i < parser.GetPrimitiveCount(); ++i)
|
|
{
|
|
if( parser.GetPrimitive(i).bIsLineBreak || parser.GetPrimitive(i).nPageBreak ||
|
|
parser.GetPrimitive(i).nBreak )
|
|
{
|
|
nFirstLineBreakIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
int nCount = parser.GetPrimitive(nFirstLineBreakIndex).dwCount;
|
|
int nTextSize = parser.GetPrimitive(nFirstLineBreakIndex).sText.size();
|
|
const char* pStr = parser.GetPrimitive(nFirstLineBreakIndex).sText.c_str();
|
|
#endif
|
|
|
|
/// 2010.10.26 dwCount는 tag도 계산되기 때문에 스트링 자체의 count를 구하기 위해서는 sText.size()를 사용해야 된다 - prodongi
|
|
int count = 0;
|
|
for (int i = 0; i < (nFirstLineBreakIndex+1); ++i)
|
|
{
|
|
count += parser.GetPrimitive(i).sText.size();
|
|
}
|
|
return count;
|
|
|
|
//return parser.GetPrimitive(nFirstLineBreakIndex).dwCount;// + parser.GetPrimitive(nFirstLineBreakIndex).sText.size();
|
|
//return parser.GetPrimitive(nFirstLineBreakIndex).sText.size();
|
|
}
|
|
|
|
|
|
void KTextPhrase::Render(KViewportObject * pViewport, bool isFront/* = false*/)
|
|
{
|
|
float fLastXPos, fLastYPos;
|
|
_SetDefaultCaretPos(&fLastXPos, &fLastYPos);
|
|
|
|
// float fCaretXPos = fLastXPos;
|
|
// float fCaretYPos = fLastYPos;
|
|
|
|
// if(m_bCaretEnable)
|
|
// {
|
|
// int a = 1;
|
|
// a = 2;
|
|
// }
|
|
|
|
int iFirstLine = (int)m_fFirstLine;
|
|
if(!m_bReverseRendering)
|
|
{
|
|
DWORD dwLineHeight = 0;
|
|
for(int i = iFirstLine; i < m_vtLineList.size(); ++i)
|
|
{
|
|
KTEXT_LINE_OBJECT * pLineObject = m_vtLineList.at(i);
|
|
|
|
for(int j = 0; j < pLineObject->vtLineObject.size(); ++j)
|
|
{
|
|
KTEXT_OBJECT & object = pLineObject->vtLineObject.at(j);
|
|
float fXPos = object.dwXPos + m_vPosition.x + pLineObject->dwXAlignPos;
|
|
float fYPos = dwLineHeight + m_vPosition.y + m_nYAlignPos + object.nOffsetY; // 그려질 오브젝트 y 오프셋 추가 적용
|
|
if( object.pRender )
|
|
{
|
|
object.pRender->SetVisibility(m_fVisibility);
|
|
object.pRender->SetPosition(fXPos,fYPos, m_vPosition.z);
|
|
|
|
object.pRender->Render(pViewport,isFront);
|
|
}
|
|
|
|
fLastXPos = fXPos + object.dwXWidth;
|
|
fLastYPos = fYPos;
|
|
}
|
|
|
|
dwLineHeight += pLineObject->dwLineHeight;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int nLineHeight = m_dwHeight + m_dwLineGap;
|
|
|
|
if( iFirstLine >= m_vtLineList.size() || iFirstLine < 0)
|
|
return;
|
|
for(int i =iFirstLine; i >= 0; --i)
|
|
{
|
|
KTEXT_LINE_OBJECT * pLineObject = m_vtLineList.at(i);
|
|
nLineHeight -= pLineObject->dwLineHeight;
|
|
|
|
for(int j = 0; j < pLineObject->vtLineObject.size(); ++j)
|
|
{
|
|
KTEXT_OBJECT & object = pLineObject->vtLineObject.at(j);
|
|
float fXPos = object.dwXPos + m_vPosition.x + pLineObject->dwXAlignPos;
|
|
float fYPos = nLineHeight + m_vPosition.y + m_nYAlignPos + object.nOffsetY; // 그려질 오브젝트 y 오프셋 추가 적용
|
|
if( object.pRender )
|
|
{
|
|
object.pRender->SetVisibility(m_fVisibility);
|
|
object.pRender->SetPosition(fXPos,fYPos, m_vPosition.z);
|
|
object.pRender->Render(pViewport,isFront);
|
|
}
|
|
|
|
fLastXPos = fXPos + object.dwXWidth;
|
|
fLastYPos = fYPos;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// if(m_bCaretEnable)
|
|
// {
|
|
// m_pCaretRender->SetVisibility(m_fVisibility);
|
|
// m_pCaretRender->SetPosition(fCaretXPos,fLastYPos,m_vPosition.z);
|
|
// m_pCaretRender->Render(pViewport,isFront);
|
|
// }
|
|
|
|
}
|
|
|
|
void KTextPhrase::SetClipRect(const KRect & rcRect)
|
|
{
|
|
|
|
for(int i = 0; i < m_vtLineList.size(); ++i)
|
|
{
|
|
KTEXT_LINE_OBJECT * pLineObject = m_vtLineList.at(i);
|
|
|
|
for(int j = 0; j < pLineObject->vtLineObject.size(); ++j)
|
|
{
|
|
KTEXT_OBJECT & object = pLineObject->vtLineObject.at(j);
|
|
object.pRender->SetClipRect(rcRect);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void KTextPhrase::SetAlign(DWORD dwAlign)
|
|
{
|
|
// 생각해 보니까 Emotiocon Layer도 똑같이 Align을 시켜줘야 한다 -_- 우우
|
|
// 이건 Emoticon Layer가 도입될때 고치도록 하자
|
|
// 생각해보니까 Emoticon은 그 Emoticon이 속한 줄을 기억하고
|
|
// 나중에 Emoticon찍을때 단순히 그 줄의 LineObject의 dwXAlignPos를 가져다가
|
|
// 보정해 주면 되므로 상관 없음 -_-
|
|
m_dwAlign = dwAlign;
|
|
|
|
// 우선 X축을 맞춰주자.
|
|
for(int i = 0; i < m_vtLineList.size(); ++i)
|
|
m_vtLineList.at(i)->dwXAlignPos = 0;
|
|
|
|
if(dwAlign & KTextRender::KTALIGN_RIGHT)
|
|
{
|
|
for(int i = 0; i < m_vtLineList.size(); ++i)
|
|
{
|
|
int nDiff = static_cast<int>( m_dwWidth - m_vtLineList.at(i)->dwLineWidth );
|
|
nDiff = max( nDiff, 0);
|
|
m_vtLineList.at(i)->dwXAlignPos = nDiff;
|
|
}
|
|
}
|
|
else if(dwAlign & KTextRender::KTALIGN_HCENTER)
|
|
{
|
|
for(int i = 0; i < m_vtLineList.size(); ++i)
|
|
{
|
|
int nDiff = static_cast<int>( m_dwWidth - m_vtLineList.at(i)->dwLineWidth );
|
|
nDiff = max( nDiff, 0);
|
|
m_vtLineList.at(i)->dwXAlignPos = nDiff / 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int nTotalHeight = 0;
|
|
|
|
if((int)m_fFirstLine >= m_vtLineList.size() )
|
|
return;
|
|
|
|
int nFirstLineHeight =m_vtLineList.at((int) m_fFirstLine)->dwLineHeight;
|
|
|
|
int nClipValue = (nFirstLineHeight * (m_fFirstLine - (float)( (int) m_fFirstLine) ) );
|
|
nTotalHeight = GetTotalLineHeigt();
|
|
|
|
m_nYAlignPos = 0;
|
|
if(dwAlign & KTextRender::KTALIGN_BOTTOM)
|
|
{
|
|
int nDiff = (int)m_dwHeight - nTotalHeight;
|
|
|
|
if(nDiff < 0)
|
|
m_nYAlignPos = 0;
|
|
else
|
|
m_nYAlignPos = nDiff;
|
|
}
|
|
else if(dwAlign & KTextRender::KTALIGN_VCENTER)
|
|
{
|
|
int nDiff = (int)m_dwHeight - nTotalHeight;
|
|
|
|
if(nDiff < 0)
|
|
m_nYAlignPos = 0;
|
|
else
|
|
m_nYAlignPos = nDiff / 2;
|
|
}
|
|
|
|
m_nYAlignPos -= nClipValue;
|
|
|
|
if(m_bReverseRendering)
|
|
m_nYAlignPos = -m_nYAlignPos;
|
|
}
|
|
|
|
DWORD KTextPhrase::GetAlign()
|
|
{
|
|
return m_dwAlign;
|
|
}
|
|
|
|
DWORD KTextPhrase::GetOverLineNumber()
|
|
{
|
|
int nHeight = -3;
|
|
int nSize = int( m_vtLineList.size() );
|
|
for(int i = 0; i < nSize; ++i)
|
|
{
|
|
nHeight += m_vtLineList.at(i)->dwLineHeight;
|
|
// 1Page를 넘어가게 되면
|
|
if(nHeight > (int)m_dwHeight)
|
|
{
|
|
return nSize - i;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void KTextPhrase::_SetDefaultCaretPos(float* fXPos, float* fYPos)
|
|
{
|
|
*fXPos = m_vPosition.x;
|
|
if(m_dwAlign & KTextRender::KTALIGN_RIGHT)
|
|
{
|
|
*fXPos += (float)m_dwWidth;
|
|
}
|
|
else if(m_dwAlign & KTextRender::KTALIGN_HCENTER)
|
|
{
|
|
*fXPos += (float)m_dwWidth / 2;
|
|
}
|
|
|
|
*fYPos = m_vPosition.y;
|
|
|
|
if(m_dwAlign & KTextRender::KTALIGN_BOTTOM)
|
|
{
|
|
*fYPos += m_dwHeight - KTextRender::GetFontHeight( KTextRender::KDEFAULT_FONT_SIZE );
|
|
}
|
|
else if(m_dwAlign & KTextRender::KTALIGN_VCENTER)
|
|
{
|
|
*fYPos += (m_dwHeight - KTextRender::GetFontHeight( KTextRender::KDEFAULT_FONT_SIZE ) ) / 2;
|
|
}
|
|
}
|
|
|
|
// 2010.05.06 - prodongi
|
|
void KTextPhrase::modifyEmoticonSize(std::string const& aniName, int width, int height)
|
|
{
|
|
DWORD lineNum = GetLineNumber();
|
|
for (DWORD num = 0; num < lineNum; ++num)
|
|
{
|
|
KTEXT_LINE_OBJECT* object = GetLineObject(num);
|
|
if (!object)
|
|
continue;
|
|
std::vector<KTEXT_OBJECT>::iterator it = object->vtLineObject.begin();
|
|
for (; it != object->vtLineObject.end(); ++it)
|
|
{
|
|
if (it->pRender)
|
|
it->pRender->modifyEmoticonSize(aniName, width, height);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
const int KTextPhrase::GetTextSize( const char* szBuf ) const
|
|
{
|
|
return KTextRender::GetTextSize( szBuf );
|
|
}
|
|
|
|
#ifndef _COUNTRY_ME_
|
|
|
|
/// 2011.01.18 - prodongi
|
|
void KTextPhrase::setSpriteScroll(bool scroll, DWORD type, float v, float margin)
|
|
{
|
|
m_spriteScrollInfo.set(scroll, type, v, margin);
|
|
|
|
for(int i = 0; i < m_vtLineList.size(); ++i)
|
|
{
|
|
KTEXT_LINE_OBJECT * pLineObject = m_vtLineList.at(i);
|
|
|
|
for(int j = 0; j < pLineObject->vtLineObject.size(); ++j)
|
|
{
|
|
KTEXT_OBJECT & object = pLineObject->vtLineObject.at(j);
|
|
object.pRender->setSpriteScroll(scroll, type, v, margin);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 2011.02.23 - prodongi
|
|
void KTextPhrase::setSpriteScrollInfo(const KTextPhrase::sSpriteScrollInfo &info)
|
|
{
|
|
m_spriteScrollInfo = info;
|
|
}
|
|
|
|
/// 2011.02.23 - prodongi
|
|
void KTextPhrase::getSpriteScrollInfo(KTextPhrase::sSpriteScrollInfo& info)
|
|
{
|
|
info = m_spriteScrollInfo;
|
|
}
|
|
|
|
/// 2011.02.23 - prodongi
|
|
void KTextPhrase::updateSpriteScrollInfo()
|
|
{
|
|
setSpriteScroll(m_spriteScrollInfo.m_scroll, m_spriteScrollInfo.m_type,
|
|
m_spriteScrollInfo.m_v, m_spriteScrollInfo.m_margin);
|
|
}
|
|
#endif
|
|
|
|
#ifdef _COUNTRY_ME_
|
|
|
|
void KTextPhrase::GetStringSize(LPCSTR lpszFontName, int nFontSize, BOOL bBold, LPCSTR lpszString, int nStringLen,
|
|
DWORD *pStringWidth, DWORD * pStringHeight)
|
|
{
|
|
std::string str;
|
|
|
|
XStringUtil::Format( str, "<font:%s><size:%d>", lpszFontName, nFontSize );
|
|
if (bBold)
|
|
str += "<b>";
|
|
|
|
str += lpszString;
|
|
|
|
if (bBold)
|
|
str += "</b>";
|
|
|
|
for( size_t i = 0; i < str.length(); ++i )
|
|
{
|
|
if ( str[i] == 0x1E )
|
|
str[i] = L'<';
|
|
if ( str[i] == 0x1F )
|
|
str[i] = L'>';
|
|
}
|
|
|
|
KSize size = GetStringSize( str.c_str(), -1, 0 );
|
|
|
|
*pStringWidth = size.width;
|
|
*pStringHeight = size.height;
|
|
}
|
|
|
|
void KTextPhrase::GetTextWidth( const wchar_t *text, size_t len, LPSIZE lpSize )
|
|
{
|
|
std::string strMultibyte = wide_to_multibyte( text );
|
|
// 2010.08.24 - prodongi
|
|
if (len > strMultibyte.length()) len = strMultibyte.length();
|
|
std::string strTemp( strMultibyte, len );
|
|
|
|
KSize size = GetStringSize( strTemp.c_str(), -1, 0 );
|
|
lpSize->cx = size.cx;
|
|
lpSize->cy = size.cy;
|
|
}
|
|
|
|
// 2010.08.24 - prodongi
|
|
std::string KTextPhrase::GetSplitString2(char const* fontName, int fontSize, std::string const& oriStr, DWORD splitWidth)
|
|
{
|
|
std::string splitStr;
|
|
DWORD w, h;
|
|
size_t size = oriStr.length();
|
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
{
|
|
splitStr = oriStr.substr(0, i);
|
|
KTextPhrase::GetStringSize(fontName, fontSize, false, splitStr.c_str(), splitStr.length(), &w, &h);
|
|
if (w >= splitWidth)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
return splitStr;
|
|
}
|
|
|
|
void KTextPhrase::Render(KViewportObject * pViewport, bool isFront/* = false*/)
|
|
{
|
|
float fLastXPos, fLastYPos;
|
|
_SetDefaultCaretPos(&fLastXPos, &fLastYPos);
|
|
|
|
// float fCaretXPos = fLastXPos;
|
|
// float fCaretYPos = fLastYPos;
|
|
|
|
// if(m_bCaretEnable)
|
|
// {
|
|
// int a = 1;
|
|
// a = 2;
|
|
// }
|
|
|
|
int iFirstLine = (int)m_fFirstLine;
|
|
if(!m_bReverseRendering)
|
|
{
|
|
DWORD dwLineHeight = 0;
|
|
for(int i = iFirstLine; i < m_vtLineList.size(); ++i)
|
|
{
|
|
KTEXT_LINE_OBJECT * pLineObject = m_vtLineList.at(i);
|
|
|
|
for(int j = 0; j < pLineObject->vtLineObject.size(); ++j)
|
|
{
|
|
KTEXT_OBJECT & object = pLineObject->vtLineObject.at(j);
|
|
float fXPos = object.dwXPos + m_vPosition.x + pLineObject->dwXAlignPos;
|
|
float fYPos = dwLineHeight + m_vPosition.y + m_nYAlignPos;
|
|
if( object.nType == 0 )
|
|
{
|
|
object.pTextRender->SetVisibility(m_fVisibility);
|
|
object.pTextRender->SetPosition(fXPos,fYPos, m_vPosition.z);
|
|
|
|
object.pTextRender->Render(pViewport,isFront);
|
|
}
|
|
else
|
|
{
|
|
object.pEmoticonRender->SetOffset( fXPos, fYPos - m_nYAlignPos );
|
|
// 이모티콘에 대한 Y축 Align이 원래 안되어 있었다;;
|
|
// SetAlign함수 참조
|
|
// 이모티콘은 현재 Line Object에서 Height값을 안가지고 있다.
|
|
// 그래서 이모티콘만 있는 경우에 Y축이 딱 크기의 절반정도 밑으로 내려간다.
|
|
object.pEmoticonRender->Render(pViewport,isFront);
|
|
}
|
|
|
|
fLastXPos = fXPos + object.dwXWidth;
|
|
fLastYPos = fYPos;
|
|
}
|
|
|
|
dwLineHeight += pLineObject->dwLineHeight + m_dwLineGap;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int nLineHeight = m_dwHeight + m_dwLineGap;
|
|
|
|
if( iFirstLine >= m_vtLineList.size() || iFirstLine < 0)
|
|
return;
|
|
for(int i =iFirstLine; i >= 0; --i)
|
|
{
|
|
KTEXT_LINE_OBJECT * pLineObject = m_vtLineList.at(i);
|
|
nLineHeight -= pLineObject->dwLineHeight;
|
|
|
|
for(int j = 0; j < pLineObject->vtLineObject.size(); ++j)
|
|
{
|
|
KTEXT_OBJECT & object = pLineObject->vtLineObject.at(j);
|
|
float fXPos = object.dwXPos + m_vPosition.x + pLineObject->dwXAlignPos;
|
|
float fYPos = nLineHeight + m_vPosition.y + m_nYAlignPos;
|
|
if( object.nType == 0 )
|
|
{
|
|
object.pTextRender->SetVisibility(m_fVisibility);
|
|
object.pTextRender->SetPosition(fXPos,fYPos, m_vPosition.z);
|
|
|
|
object.pTextRender->Render(pViewport,isFront);
|
|
}
|
|
else
|
|
{
|
|
object.pEmoticonRender->SetOffset( fXPos, fYPos );
|
|
object.pEmoticonRender->Render(pViewport,isFront);
|
|
}
|
|
|
|
fLastXPos = fXPos + object.dwXWidth;
|
|
fLastYPos = fYPos;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// if(m_bCaretEnable)
|
|
// {
|
|
// m_pCaretRender->SetVisibility(m_fVisibility);
|
|
// m_pCaretRender->SetPosition(fCaretXPos,fLastYPos,m_vPosition.z);
|
|
// m_pCaretRender->Render(pViewport,isFront);
|
|
// }
|
|
|
|
}
|
|
|
|
void KTextPhrase::SetClipRect(const KRect & rcRect)
|
|
{
|
|
|
|
for(int i = 0; i < m_vtLineList.size(); ++i)
|
|
{
|
|
KTEXT_LINE_OBJECT * pLineObject = m_vtLineList.at(i);
|
|
|
|
for(int j = 0; j < pLineObject->vtLineObject.size(); ++j)
|
|
{
|
|
KTEXT_OBJECT & object = pLineObject->vtLineObject.at(j);
|
|
if ( object.nType == 0 )
|
|
object.pTextRender->SetClipRect(rcRect);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void KTextPhrase::SetAlign(DWORD dwAlign)
|
|
{
|
|
// 생각해 보니까 Emotiocon Layer도 똑같이 Align을 시켜줘야 한다 -_- 우우
|
|
// 이건 Emoticon Layer가 도입될때 고치도록 하자
|
|
// 생각해보니까 Emoticon은 그 Emoticon이 속한 줄을 기억하고
|
|
// 나중에 Emoticon찍을때 단순히 그 줄의 LineObject의 dwXAlignPos를 가져다가
|
|
// 보정해 주면 되므로 상관 없음 -_-
|
|
m_dwAlign = dwAlign;
|
|
|
|
// 우선 X축을 맞춰주자.
|
|
for(int i = 0; i < m_vtLineList.size(); ++i)
|
|
m_vtLineList.at(i)->dwXAlignPos = 0;
|
|
|
|
if(dwAlign & KTextParagraph::KTALIGN_RIGHT)
|
|
{
|
|
for(int i = 0; i < m_vtLineList.size(); ++i)
|
|
{
|
|
int nDiff = static_cast<int>( m_dwWidth - m_vtLineList.at(i)->dwLineWidth );
|
|
nDiff = max( nDiff, 0);
|
|
m_vtLineList.at(i)->dwXAlignPos = nDiff;
|
|
}
|
|
}
|
|
else if(dwAlign & KTextParagraph::KTALIGN_HCENTER)
|
|
{
|
|
for(int i = 0; i < m_vtLineList.size(); ++i)
|
|
{
|
|
int nDiff = static_cast<int>( m_dwWidth - m_vtLineList.at(i)->dwLineWidth );
|
|
nDiff = max( nDiff, 0);
|
|
m_vtLineList.at(i)->dwXAlignPos = nDiff / 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int nTotalHeight = 0;
|
|
|
|
if((int)m_fFirstLine >= m_vtLineList.size() )
|
|
return;
|
|
|
|
int nFirstLineHeight =m_vtLineList.at((int) m_fFirstLine)->dwLineHeight;
|
|
|
|
int nClipValue = (nFirstLineHeight * (m_fFirstLine - (float)( (int) m_fFirstLine) ) );
|
|
nTotalHeight = GetTotalLineHeigt();
|
|
|
|
m_nYAlignPos = 0;
|
|
if(dwAlign & KTextParagraph::KTALIGN_BOTTOM)
|
|
{
|
|
int nDiff = (int)m_dwHeight - nTotalHeight;
|
|
|
|
if(nDiff < 0)
|
|
m_nYAlignPos = 0;
|
|
else
|
|
m_nYAlignPos = nDiff;
|
|
}
|
|
else if(dwAlign & KTextParagraph::KTALIGN_VCENTER)
|
|
{
|
|
int nDiff = (int)m_dwHeight - nTotalHeight;
|
|
|
|
if(nDiff < 0)
|
|
m_nYAlignPos = 0;
|
|
else
|
|
m_nYAlignPos = nDiff / 2;
|
|
}
|
|
|
|
m_nYAlignPos -= nClipValue;
|
|
|
|
if(m_bReverseRendering)
|
|
m_nYAlignPos = -m_nYAlignPos;
|
|
}
|
|
|
|
DWORD KTextPhrase::GetAlign()
|
|
{
|
|
return m_dwAlign;
|
|
}
|
|
|
|
DWORD KTextPhrase::GetOverLineNumber()
|
|
{
|
|
int nHeight = -3;
|
|
int nSize = int( m_vtLineList.size() );
|
|
for(int i = 0; i < nSize; ++i)
|
|
{
|
|
nHeight += m_vtLineList.at(i)->dwLineHeight;
|
|
// 1Page를 넘어가게 되면
|
|
if(nHeight > (int)m_dwHeight)
|
|
{
|
|
return nSize - i;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void KTextPhrase::_SetDefaultCaretPos(float* fXPos, float* fYPos)
|
|
{
|
|
*fXPos = m_vPosition.x;
|
|
if(m_dwAlign & KTextParagraph::KTALIGN_RIGHT)
|
|
{
|
|
*fXPos += (float)m_dwWidth;
|
|
}
|
|
else if(m_dwAlign & KTextParagraph::KTALIGN_HCENTER)
|
|
{
|
|
*fXPos += (float)m_dwWidth / 2;
|
|
}
|
|
|
|
*fYPos = m_vPosition.y;
|
|
|
|
if(m_dwAlign & KTextParagraph::KTALIGN_BOTTOM)
|
|
{
|
|
*fYPos += m_dwHeight - KTextRender::GetFontHeight( KFontManager::KDEFAULT_FONT_SIZE );
|
|
}
|
|
else if(m_dwAlign & KTextParagraph::KTALIGN_VCENTER)
|
|
{
|
|
*fYPos += (m_dwHeight - KTextRender::GetFontHeight( KFontManager::KDEFAULT_FONT_SIZE ) ) / 2;
|
|
}
|
|
}
|
|
|
|
#endif |