Files
2026-06-01 12:46:52 +02:00

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