// KTextPhrase.cpp: implementation of the KTextPhrase class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "KTextPhrase.h" #include "KTextParser.h" #include "KRenderObject.h" #include //#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& 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, "" , "" ); if( bStrike ) AttachTag(rOutText, "", "" ); if( bInverse ) AttachTag(rOutText, "" , "" ); if( bBold ) AttachTag(rOutText, "" , "" ); if( bShadow ) AttachTag(rOutText, "", "" ); if( bOutline ) AttachTag(rOutText, "" , "" ); if( bGlow ) AttachTag(rOutText, "" , "" ); if( bGlow2X ) AttachTag(rOutText, "<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>%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( "%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( 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( 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::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, "", lpszFontName, nFontSize ); if (bBold) str += ""; str += lpszString; if (bBold) str += ""; 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( 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( 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