683 lines
20 KiB
C++
683 lines
20 KiB
C++
#include "stdafx.h"
|
|
#ifdef _COUNTRY_ME_
|
|
|
|
#include "KTextParser.h"
|
|
#include "KTextLayout.h"
|
|
#include "KTextEmoticonRender.h"
|
|
#include <toolkit/XStringUtil.h>
|
|
#include "KTextCacheManager.h"
|
|
#include "KPrimitiveSprite.h"
|
|
#include "KViewport.h"
|
|
#include <toolkit/XEnv.h>
|
|
#include "KTextParagraph.h"
|
|
#include "Resource.h"
|
|
|
|
K3DRenderDevice * KTextLayout2::m_pDevice = NULL;
|
|
PangoContext* KTextLayout2::s_pPangoContext = NULL;
|
|
|
|
void KTextLayout2::InitLayoutEngine( K3DRenderDevice * pDevice )
|
|
{
|
|
m_pDevice = pDevice;
|
|
|
|
HANDLE hFile = CreateFile( "etc\\fonts\\fonts.conf", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
|
|
if ( hFile == INVALID_HANDLE_VALUE )
|
|
{
|
|
hFile = CreateFile( "etc", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
|
|
if ( hFile == INVALID_HANDLE_VALUE )
|
|
CreateDirectory( "etc", NULL );
|
|
hFile = CreateFile( "etc\\fonts", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
|
|
if ( hFile == INVALID_HANDLE_VALUE )
|
|
CreateDirectory( "etc\\fonts", NULL );
|
|
|
|
HRSRC hRsrc = FindResource( NULL, (LPCSTR)IDR_FONTCONFIG, "XML" );
|
|
DWORD dwSize = SizeofResource( NULL, hRsrc );
|
|
HGLOBAL hGlobal = LoadResource( NULL, hRsrc );
|
|
LPVOID pBuf = LockResource( hGlobal );
|
|
|
|
DWORD dwWritten;
|
|
hFile = CreateFile( "etc\\fonts\\fonts.conf", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
|
|
WriteFile( hFile, pBuf, dwSize, &dwWritten, NULL );
|
|
CloseHandle( hFile );
|
|
}
|
|
|
|
PangoFontMap* pFontMap = pango_cairo_font_map_new_for_font_type( CAIRO_FONT_TYPE_FT );
|
|
if ( !pFontMap )
|
|
pFontMap = pango_cairo_font_map_get_default();
|
|
s_pPangoContext = pango_font_map_create_context( pFontMap );
|
|
g_object_unref( pFontMap );
|
|
|
|
cairo_font_options_t* option;
|
|
option = cairo_font_options_create();
|
|
cairo_font_options_set_antialias ( option, CAIRO_ANTIALIAS_GRAY );
|
|
pango_cairo_context_set_font_options( s_pPangoContext, option );
|
|
cairo_font_options_destroy(option);
|
|
|
|
pango_context_set_base_dir( s_pPangoContext, (PangoDirection)ENV().GetInt( "layout_dir", PANGO_DIRECTION_NEUTRAL ) );
|
|
}
|
|
|
|
|
|
void KTextLayout2::DestroyLayoutEngine()
|
|
{
|
|
g_object_unref( s_pPangoContext );
|
|
}
|
|
|
|
KParagraphLayout::KParagraphLayout( int nWidth, int nHeight, int nSpacing, DWORD dwAlign )
|
|
: m_nWidth( nWidth ), m_nHeight( nHeight ), m_nSpacing( nSpacing ), m_dwAlign( dwAlign )
|
|
{
|
|
|
|
m_layout = pango_layout_new( KTextLayout2::GetPangoContext() );
|
|
if ( nWidth >= 0 )
|
|
pango_layout_set_width( m_layout, nWidth * PANGO_SCALE );
|
|
else
|
|
pango_layout_set_width( m_layout, -1 );
|
|
if ( nHeight >= 0 )
|
|
pango_layout_set_width( m_layout, nHeight * PANGO_SCALE );
|
|
else
|
|
pango_layout_set_width( m_layout, nHeight );
|
|
|
|
pango_layout_set_auto_dir( m_layout, ENV().GetInt( "layout_auto", true ) );
|
|
}
|
|
|
|
KParagraphLayout::~KParagraphLayout()
|
|
{
|
|
g_object_unref( m_layout );
|
|
}
|
|
|
|
|
|
void KParagraphLayout::Layout( KTextParagraph* pPara )
|
|
{
|
|
PangoFontDescription *desc;
|
|
std::string strFont;
|
|
|
|
XStringUtil::Format( strFont, "%s %d", pPara->GetAttr()->strFontName.c_str(), pPara->GetAttr()->nFontSize );
|
|
|
|
if ( m_nWidth >= 0 )
|
|
pango_layout_set_width( m_layout, m_nWidth * PANGO_SCALE );
|
|
else
|
|
pango_layout_set_width( m_layout, -1 );
|
|
|
|
|
|
desc = pango_font_description_from_string( strFont.c_str() );
|
|
if ( pPara->GetAttr()->bBold )
|
|
pango_font_description_set_weight( desc, PANGO_WEIGHT_BOLD );
|
|
pango_layout_set_font_description( m_layout, desc );
|
|
pango_font_description_free( desc );
|
|
|
|
SetAlign( m_dwAlign );
|
|
}
|
|
|
|
void KParagraphLayout::SetAlign( DWORD dwAlign )
|
|
{
|
|
if ( (dwAlign & KTextParagraph::KTALIGN_HCENTER) == KTextParagraph::KTALIGN_HCENTER )
|
|
pango_layout_set_alignment( m_layout, PANGO_ALIGN_CENTER );
|
|
else if ( (dwAlign & KTextParagraph::KTALIGN_RIGHT) == KTextParagraph::KTALIGN_RIGHT )
|
|
pango_layout_set_alignment( m_layout, PANGO_ALIGN_RIGHT );
|
|
else
|
|
pango_layout_set_alignment( m_layout, PANGO_ALIGN_LEFT );
|
|
}
|
|
|
|
int KParagraphLayout::GetLineCount( KTextParagraph* pPara, int nOffsetX )
|
|
{
|
|
Layout( pPara );
|
|
|
|
PangoAttrList* pAttrList = pPara->GetPangoAttrListWithoutColor();
|
|
pango_layout_set_attributes( m_layout, pAttrList );
|
|
pango_attr_list_unref( pAttrList );
|
|
|
|
pango_layout_set_indent( m_layout, nOffsetX * PANGO_SCALE );
|
|
pango_layout_set_text( m_layout, pPara->GetString().c_str(), -1 );
|
|
|
|
return pango_layout_get_line_count( m_layout );
|
|
}
|
|
|
|
KSize KParagraphLayout::GetActualSize( KTextParagraph* pPara, int nOffsetX )
|
|
{
|
|
Layout( pPara );
|
|
|
|
PangoAttrList* pAttrList = pPara->GetPangoAttrListWithoutColor();
|
|
pango_layout_set_attributes( m_layout, pAttrList );
|
|
pango_attr_list_unref( pAttrList );
|
|
|
|
pango_layout_set_indent( m_layout, nOffsetX * PANGO_SCALE );
|
|
pango_layout_set_text( m_layout, pPara->GetString().c_str(), -1 );
|
|
|
|
PangoRectangle rcLog;
|
|
pango_layout_get_pixel_extents( m_layout, NULL, &rcLog );
|
|
|
|
if ( pango_layout_get_line_count( m_layout ) <= 1 )
|
|
return KSize( rcLog.x + rcLog.width - nOffsetX, rcLog.y + rcLog.height );
|
|
else
|
|
return KSize( rcLog.x + rcLog.width, rcLog.y + rcLog.height );
|
|
}
|
|
|
|
void KParagraphLayout::_Render( cairo_t* cr, LPCSTR szText, double r, double g, double b, double a, double dX, double dY )
|
|
{
|
|
cairo_set_source_rgba( cr, r, g, b, a );
|
|
|
|
cairo_move_to( cr, dX, dY);
|
|
pango_layout_set_text( m_layout, szText, -1 );
|
|
pango_cairo_show_layout( cr, m_layout );
|
|
}
|
|
|
|
|
|
void KParagraphLayout::Render( cairo_t* cr, KTextParagraph* pParagraph, int nX, int nY )
|
|
{
|
|
pango_cairo_update_context( cr, KTextLayout2::GetPangoContext() );
|
|
pango_layout_context_changed( m_layout );
|
|
|
|
|
|
Layout( pParagraph );
|
|
|
|
PangoAttrList* pAttrList;
|
|
|
|
pAttrList = pParagraph->GetPangoAttrListWithoutColor();
|
|
pango_layout_set_attributes( m_layout, pAttrList );
|
|
pango_attr_list_unref( pAttrList );
|
|
|
|
pango_layout_set_indent( m_layout, nX * PANGO_SCALE );
|
|
|
|
if ( pParagraph->GetAttr()->bShadow )
|
|
{
|
|
double dOffset = (pParagraph->GetAttr()->nFontSize / 10. );
|
|
_Render( cr, pParagraph->GetString().c_str(), 0, 0, 0, 0.8, dOffset, nY + dOffset );
|
|
}
|
|
|
|
pAttrList = pParagraph->GetPangoAttrList();
|
|
pango_layout_set_attributes( m_layout, pAttrList );
|
|
pango_attr_list_unref( pAttrList );
|
|
|
|
_Render( cr, pParagraph->GetString().c_str(),
|
|
((pParagraph->GetAttr()->dwColor & 0xff0000) >> 16) / 255.0,
|
|
((pParagraph->GetAttr()->dwColor & 0x00ff00) >> 8) / 255.0,
|
|
((pParagraph->GetAttr()->dwColor & 0x0000ff) >> 0) / 255.0,
|
|
1.0, 0, nY );
|
|
}
|
|
|
|
KTextLayout2::KTextLayout2()
|
|
: m_nWidth( 0 ), m_nHeight( 0 ), m_nSpacing( KDEFAULT_LINE_SPACING ),
|
|
m_prSprite( NULL ), m_spResSprite( NULL ), m_spTexture( NULL ), m_dwAlign( KTextParagraph::KTALIGN_HCENTER | KTextParagraph::KTALIGN_VCENTER )
|
|
{
|
|
m_fViewOffsetY = 0;
|
|
m_fAlignOffsetY = 0;
|
|
m_sizeTexture.cx = 0;
|
|
m_sizeTexture.cy = 0;
|
|
}
|
|
KTextLayout2::KTextLayout2( int nWidth, int nHeight, int nSpacing )
|
|
: m_nWidth( nWidth ), m_nHeight( nHeight ), m_nSpacing( nSpacing ),
|
|
m_prSprite( NULL ), m_spResSprite( NULL ), m_spTexture( NULL ), m_dwAlign( KTextParagraph::KTALIGN_HCENTER | KTextParagraph::KTALIGN_VCENTER )
|
|
{
|
|
m_fViewOffsetY = 0;
|
|
m_fAlignOffsetY = 0;
|
|
m_sizeTexture.cx = 0;
|
|
m_sizeTexture.cy = 0;
|
|
}
|
|
|
|
KTextLayout2::~KTextLayout2(void)
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void KTextLayout2::SetClipRect(const KRect & rcRect)
|
|
{
|
|
m_rcClipRect = rcRect;
|
|
m_prSprite->SetClipRect( &m_rcClipRect );
|
|
}
|
|
|
|
extern BYTE Get5x5FilteredAlphaValue( LPBYTE pSrc, int x, int y, int w, int h, int nStride );
|
|
|
|
void BitBlt_Premultiplied2Nonmultiplied2( LPVOID pSrc, LPVOID pDst, int nWidth, int nHeight, int nSrcStride, int nDstStride, bool bGlow )
|
|
{
|
|
LPBYTE pbSrc = (LPBYTE)pSrc;
|
|
LPBYTE pbDst = (LPBYTE)pDst;
|
|
LPDWORD pdwSrc, pdwDst;
|
|
|
|
KColor pxSrc, pxDst, pxFinal;
|
|
int x, y;
|
|
|
|
if ( bGlow )
|
|
{
|
|
for ( y = 0; y < nHeight; y++ )
|
|
{
|
|
pdwSrc = (DWORD *)pbSrc;
|
|
pdwDst = (DWORD *)pbDst;
|
|
|
|
for( x = 0; x < nWidth; x++ )
|
|
{
|
|
BYTE bAlpha = Get5x5FilteredAlphaValue( (LPBYTE)pSrc, x, y, nWidth, nHeight, nSrcStride );
|
|
pxSrc.color = *pdwSrc;
|
|
pxDst.color = *pdwDst;
|
|
|
|
if ( bAlpha > 0 )
|
|
{
|
|
pxFinal.a = bAlpha + (255 - bAlpha) * pxDst.a / 255;;
|
|
pxFinal.g = static_cast <BYTE> ( ( 0 * 255 + ( 255.0 - bAlpha ) * pxDst.g * pxDst.a / 255 ) / pxFinal.a );
|
|
pxFinal.b = static_cast <BYTE> ( ( 74 * 255 + ( 255.0 - bAlpha ) * pxDst.b * pxDst.a / 255 ) / pxFinal.a );
|
|
pxFinal.r = static_cast <BYTE> ( (128 * 255 + ( 255.0 - bAlpha ) * pxDst.b * pxDst.a / 255 ) / pxFinal.a );
|
|
*pdwDst++ = pxFinal.color;
|
|
}
|
|
else
|
|
pdwDst++;
|
|
pdwSrc++;
|
|
}
|
|
pbSrc += nSrcStride;
|
|
pbDst += nDstStride;
|
|
}
|
|
}
|
|
|
|
pbSrc = (LPBYTE)pSrc;
|
|
pbDst = (LPBYTE)pDst;
|
|
|
|
for ( y = 0; y < nHeight; y++ )
|
|
{
|
|
pdwSrc = (DWORD *)pbSrc;
|
|
pdwDst = (DWORD *)pbDst;
|
|
|
|
for( x = 0; x < nWidth; x++ )
|
|
{
|
|
pxSrc.color = *pdwSrc++;
|
|
pxDst.color = *pdwDst;
|
|
|
|
if ( pxSrc.a > 0 )
|
|
{
|
|
pxFinal.a = pxSrc.a + ( 255 - pxSrc.a ) * pxDst.a / 255;
|
|
|
|
pxFinal.r = static_cast <BYTE> ( ( pxSrc.r * 255 + ( 255.0 - pxSrc.a ) * pxDst.a * pxDst.r / 255) / pxFinal.a );
|
|
pxFinal.g = static_cast <BYTE> ( ( pxSrc.g * 255 + ( 255.0 - pxSrc.a ) * pxDst.a * pxDst.g / 255) / pxFinal.a );
|
|
pxFinal.b = static_cast <BYTE> ( ( pxSrc.b * 255 + ( 255.0 - pxSrc.a ) * pxDst.a * pxDst.b / 255) / pxFinal.a );
|
|
|
|
*pdwDst++ = pxFinal.color;
|
|
}
|
|
else
|
|
pdwDst++;
|
|
}
|
|
|
|
pbSrc += nSrcStride;
|
|
pbDst += nDstStride;
|
|
}
|
|
}
|
|
|
|
void KTextLayout2::Clear()
|
|
{
|
|
m_spResSprite = NULL;
|
|
m_spTexture = NULL;
|
|
SAFE_DELETE( m_prSprite );
|
|
|
|
for ( ilistEmoticon itor = m_listEmoticons.begin(); itor != m_listEmoticons.end(); ++itor )
|
|
delete *itor;
|
|
m_listEmoticons.clear();
|
|
}
|
|
|
|
// 2010.09.03 - prodongi
|
|
void KTextLayout2::AddString( LPCSTR lpszString, float fZPos, bool bTagEnable, bool bDummy1, bool bDummy2, bool isScroll, DWORD maxWidth, bool isSpriteScroll )
|
|
//void KTextLayout2::AddString( LPCSTR lpszString, float fZPos, bool bTagEnable, bool bDummy1, bool bDummy2 )
|
|
{
|
|
Clear();
|
|
|
|
m_strText = lpszString;
|
|
|
|
m_prSprite = new KSpritePrimitive(false);
|
|
m_spResSprite = new KResSprite;
|
|
|
|
KTextParser parser;
|
|
|
|
DWORD dwHALign = ( KTextParagraph::KTALIGN_LEFT & m_dwAlign ) | (KTextParagraph::KTALIGN_HCENTER & m_dwAlign);
|
|
DWORD dwVALign = ( KTextParagraph::KTALIGN_BOTTOM & m_dwAlign ) | (KTextParagraph::KTALIGN_VCENTER & m_dwAlign);
|
|
|
|
parser.SetAlign( dwHALign, dwVALign );
|
|
// 2010.09.03 - prodongi
|
|
DWORD _maxWidth = (maxWidth) ? maxWidth : (DWORD)m_nWidth;
|
|
parser.AddString( lpszString, _maxWidth/*m_nWidth*/, bTagEnable, false, isScroll );
|
|
//parser.AddString( lpszString, m_nWidth, bTagEnable );
|
|
|
|
m_dwAlign = parser.GetAlign();
|
|
int nParaCount = parser.GetParagraphCount();
|
|
|
|
int nX = 0, nMaxWidth = 0;
|
|
int nY = 0;
|
|
|
|
for ( int i = 0; i < nParaCount; ++i )
|
|
{
|
|
KTextParagraph* pPara = parser.GetTextParagraph( i );
|
|
if ( pPara->m_dwOffsetX )
|
|
nX = pPara->m_dwOffsetX;
|
|
|
|
if ( pPara->m_bEmoticon )
|
|
{
|
|
KTextEmoticon* pEmoticon;
|
|
pEmoticon = new KTextEmoticon( KTextEmoticon::TYPE_NORMAL, nX, nY, 0, 0, pPara->m_strText.c_str(), "ui_frame.spr", fZPos );
|
|
pEmoticon->Initialize( false );
|
|
pEmoticon->SetOffset( m_vPosition.x, m_vPosition.y );
|
|
nX += pEmoticon->GetWidth();
|
|
nMaxWidth = max( nX, nMaxWidth );
|
|
m_listEmoticons.push_back( pEmoticon );
|
|
}
|
|
else
|
|
{
|
|
KParagraphLayout layout( m_nWidth, -1, m_nSpacing, m_dwAlign );
|
|
KSize size = layout.GetActualSize( pPara, nX );
|
|
|
|
if ( layout.GetLineCount( pPara, nX ) > 1 || ( KTextParagraph::KTALIGN_HCENTER & m_dwAlign ) == KTextParagraph::KTALIGN_HCENTER ) // 문단이 실제 한줄이 넘어가면 무조건 line break가 있다고 가정한다.
|
|
{
|
|
nMaxWidth = max( size.cx, nMaxWidth );
|
|
nX = 0;
|
|
nY += size.height + m_nSpacing;
|
|
}
|
|
else if (pPara->GetLineBreak() || i == nParaCount - 1 )
|
|
{
|
|
nMaxWidth = max( nX + size.cx, nMaxWidth );
|
|
nX = 0;
|
|
nY += size.height + m_nSpacing;
|
|
}
|
|
else
|
|
{
|
|
nX += size.width;
|
|
nMaxWidth = max( nX, nMaxWidth );
|
|
}
|
|
}
|
|
}
|
|
|
|
m_sizeTexture.cx = nMaxWidth;
|
|
// m_sizeTexture.cx = m_nWidth;
|
|
m_sizeTexture.cy = nY;
|
|
if ( (m_dwAlign & KTextParagraph::KTALIGN_VCENTER) == KTextParagraph::KTALIGN_VCENTER )
|
|
m_fAlignOffsetY = (m_nHeight - nY) / 2;
|
|
else if ( (m_dwAlign & KTextParagraph::KTALIGN_BOTTOM) == KTextParagraph::KTALIGN_BOTTOM )
|
|
m_fAlignOffsetY = m_nHeight - nY;
|
|
else
|
|
m_fAlignOffsetY = 0;
|
|
|
|
m_spTexture = KTextCacheManager::GetInstance()->FindCache( lpszString, 0, "NONE", 0, m_sizeTexture.cx, m_sizeTexture.cy, 0, 0);
|
|
|
|
bool bTextureExist = false;
|
|
if (m_spTexture != NULL)
|
|
{
|
|
if (isSpriteScroll)
|
|
{
|
|
m_spResSprite->SetTexture(m_spTexture, m_spTexture->GetTextOriImgRect());
|
|
m_prSprite->SetRes(m_spResSprite);
|
|
m_prSprite->setScrollImgUv(m_spTexture->GetTextOriImgWidth(), m_spTexture->GetTextOriImgHeight());
|
|
}
|
|
else
|
|
{
|
|
m_spResSprite->SetTexture(m_spTexture, NULL);
|
|
m_prSprite->SetRes(m_spResSprite);
|
|
}
|
|
m_prSprite->SetPosition( m_vPosition.x, m_vPosition.y + m_fAlignOffsetY, m_vPosition.z );
|
|
return;
|
|
}
|
|
|
|
KRect rcTexRect;
|
|
rcTexRect.left = 0; rcTexRect.top = 0; rcTexRect.right = m_sizeTexture.cx; rcTexRect.bottom = m_sizeTexture.cy;
|
|
|
|
m_spTexture = m_pDevice->CreateTexture( m_sizeTexture.cx, m_sizeTexture.cy, K3DFMT_A8R8G8B8 );
|
|
assert( m_spTexture && "m_spTexture = m_pDevice->CreateTexture(dwTexWidth,dwTexHeight, K3DFMT_A8R8G8B8 )");
|
|
if (m_spTexture == NULL)
|
|
return;
|
|
|
|
|
|
nX = 0;
|
|
nY = 0;
|
|
nMaxWidth = 0;
|
|
|
|
cairo_surface_t* surface = NULL;
|
|
cairo_t* cr = NULL;
|
|
|
|
surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, m_sizeTexture.cx, m_sizeTexture.cy );
|
|
cr = cairo_create( surface );
|
|
|
|
BYTE* pSrcBuf;
|
|
void* pDstBuf;
|
|
int nSrcStride;
|
|
int nDstStride;
|
|
|
|
pSrcBuf = cairo_image_surface_get_data( surface );
|
|
nSrcStride = cairo_image_surface_get_stride( surface );
|
|
|
|
m_spTexture->LockRect(&rcTexRect, reinterpret_cast<void **>(&pDstBuf), nDstStride);
|
|
assert( pDstBuf && "m_spTexture->LockRect(&rcTexRect, reinterpret_cast<void **>(&pDstBuf), nDstStride);");
|
|
if( !pDstBuf)
|
|
return;
|
|
|
|
for ( int i = 0; i < nParaCount; ++i )
|
|
{
|
|
KTextParagraph* pPara = parser.GetTextParagraph( i );
|
|
if ( pPara->m_dwOffsetX )
|
|
nX = pPara->m_dwOffsetX;
|
|
|
|
if ( pPara->m_bEmoticon )
|
|
{
|
|
KTextEmoticon* pEmoticon;
|
|
pEmoticon = new KTextEmoticon( KTextEmoticon::TYPE_NORMAL, nX, nY, 0, 0, pPara->m_strText.c_str(), "ui_frame.spr", fZPos );
|
|
pEmoticon->Initialize( false );
|
|
|
|
nX += pEmoticon->GetWidth();
|
|
nMaxWidth = max( nX, nMaxWidth );
|
|
delete pEmoticon;
|
|
}
|
|
else
|
|
{
|
|
cairo_set_source_rgba( cr, 0, 0, 0, 0 );
|
|
cairo_paint( cr );
|
|
|
|
KParagraphLayout layout( m_nWidth, -1, m_nSpacing, m_dwAlign );
|
|
|
|
KSize size = layout.GetActualSize( pPara, nX );
|
|
|
|
layout.Render( cr, pPara, nX, nY );
|
|
|
|
/*
|
|
extern bool g_bSaveToPng;
|
|
if ( g_bSaveToPng )
|
|
{
|
|
static int nFileNo = 0;
|
|
std::string strFileName;
|
|
|
|
XStringUtil::Format( strFileName, "PNG-%06d.png", nFileNo++ );
|
|
cairo_surface_write_to_png( surface, strFileName.c_str() );
|
|
}
|
|
*/
|
|
|
|
BitBlt_Premultiplied2Nonmultiplied2( pSrcBuf, pDstBuf, m_sizeTexture.cx, m_sizeTexture.cy, nSrcStride, nDstStride, pPara->GetAttr()->bGlow );
|
|
|
|
if ( layout.GetLineCount( pPara, nX ) > 1 || ( KTextParagraph::KTALIGN_HCENTER & m_dwAlign ) == KTextParagraph::KTALIGN_HCENTER ) // 문단이 실제 한줄이 넘어가면 무조건 line break가 있다고 가정한다.
|
|
{
|
|
nMaxWidth = max( size.cx, nMaxWidth );
|
|
nX = 0;
|
|
nY += size.height + m_nSpacing;
|
|
}
|
|
else if ( pPara->GetLineBreak() || i == nParaCount - 1 )
|
|
{
|
|
nX = 0;
|
|
nMaxWidth = max( nX + size.cx, nMaxWidth );
|
|
nY += size.height + m_nSpacing;
|
|
}
|
|
else
|
|
{
|
|
nX += size.width;
|
|
nMaxWidth = max( nX, nMaxWidth );
|
|
}
|
|
}
|
|
}
|
|
m_spTexture->Unlock();
|
|
if ( cr )
|
|
cairo_destroy( cr );
|
|
if ( surface )
|
|
cairo_surface_destroy( surface );
|
|
|
|
if (isSpriteScroll)
|
|
{
|
|
rcTexRect.right = m_nWidth; /// 컨트롤의 넓이를 넣어줘야 된다
|
|
}
|
|
|
|
m_spResSprite->SetTexture(m_spTexture, &rcTexRect);
|
|
m_prSprite->SetRes(m_spResSprite);
|
|
m_prSprite->SetPosition( m_vPosition.x, m_vPosition.y + m_fAlignOffsetY, m_vPosition.z );
|
|
|
|
if (isSpriteScroll)
|
|
{
|
|
m_spTexture->SetTextOriImgRect(rcTexRect);
|
|
m_spTexture->SetTextOriImgSize(m_nWidth, nY);
|
|
m_prSprite->setScrollImgUv(m_nWidth, nY);
|
|
}
|
|
|
|
KTextCacheManager::GetInstance()->RegisterCache( lpszString, 0, "NONE", 0, m_sizeTexture.cx, m_sizeTexture.cy, 0, 0, m_spTexture);
|
|
}
|
|
|
|
void KTextLayout2::SetPosition( float fX, float fY, float fZ )
|
|
{
|
|
m_vPosition.x = fX;
|
|
m_vPosition.y = fY;
|
|
m_vPosition.z = fZ;
|
|
|
|
for ( ilistEmoticon itor = m_listEmoticons.begin(); itor != m_listEmoticons.end(); ++itor )
|
|
(*itor)->SetOffset( m_vPosition.x, m_vPosition.y + m_fAlignOffsetY );
|
|
if ( m_prSprite )
|
|
{
|
|
m_prSprite->SetPosition( m_vPosition.x, m_vPosition.y + m_fAlignOffsetY - m_fViewOffsetY, m_vPosition.z );
|
|
}
|
|
}
|
|
|
|
void KTextLayout2::SetAddPosition( float fAddX, float fAddY, float fAddZ )
|
|
{
|
|
m_vPosition.x += fAddX;
|
|
m_vPosition.y += fAddY;
|
|
m_vPosition.z += fAddZ;
|
|
|
|
for ( ilistEmoticon itor = m_listEmoticons.begin(); itor != m_listEmoticons.end(); ++itor )
|
|
(*itor)->SetOffset( m_vPosition.x, m_vPosition.y + m_fAlignOffsetY);
|
|
if ( m_prSprite )
|
|
m_prSprite->SetPosition( m_vPosition.x, m_vPosition.y + m_fAlignOffsetY - m_fViewOffsetY, m_vPosition.z );
|
|
}
|
|
|
|
void KTextLayout2::Render(KViewportObject * pViewport, bool isFront)
|
|
{
|
|
if ( m_prSprite )
|
|
pViewport->Register( m_prSprite, isFront );
|
|
|
|
for ( ilistEmoticon itor = m_listEmoticons.begin(); itor != m_listEmoticons.end(); ++itor )
|
|
(*itor)->Render( pViewport, isFront );
|
|
|
|
if (m_spriteScrollInfo.m_scroll && m_prSprite)
|
|
m_prSprite->SetVisibility(m_fVisibility);
|
|
}
|
|
|
|
|
|
DWORD KTextLayout2::GetTotalLineHeigt()
|
|
{
|
|
const KRect* rect = m_prSprite->GetClipRect();
|
|
return abs(rect->bottom - rect->top);
|
|
}
|
|
|
|
|
|
KSize KTextLayout2::GetLayoutSize( KTextParagraph* pParagraph, int nLimitWidth )
|
|
{
|
|
PangoLayout* layout = pango_layout_new( KTextLayout2::GetPangoContext() );
|
|
if ( nLimitWidth >= 0 )
|
|
pango_layout_set_width( layout, nLimitWidth * PANGO_SCALE );
|
|
else
|
|
pango_layout_set_width( layout, -1 );
|
|
|
|
pango_layout_set_auto_dir( layout, ENV().GetInt( "layout_auto", true ) );
|
|
|
|
if ( pParagraph->m_bEmoticon )
|
|
return KSize( 0, 0 );
|
|
|
|
PangoFontDescription *desc;
|
|
std::string strFont;
|
|
|
|
XStringUtil::Format( strFont, "%s %d", pParagraph->GetAttr()->strFontName.c_str(), pParagraph->GetAttr()->nFontSize );
|
|
|
|
desc = pango_font_description_from_string( strFont.c_str() );
|
|
if ( pParagraph->GetAttr()->bBold )
|
|
pango_font_description_set_weight( desc, PANGO_WEIGHT_BOLD );
|
|
pango_layout_set_font_description( layout, desc );
|
|
pango_font_description_free( desc );
|
|
|
|
PangoAttrList* pAttrList = pParagraph->GetPangoAttrListWithoutColor();
|
|
pango_layout_set_attributes( layout, pAttrList );
|
|
pango_attr_list_unref( pAttrList );
|
|
|
|
pango_layout_set_text( layout, pParagraph->GetString().c_str(), -1 );
|
|
|
|
int nWidth, nHeight;
|
|
pango_layout_get_pixel_size( layout, &nWidth, &nHeight );
|
|
|
|
g_object_unref( layout );
|
|
|
|
return KSize( nWidth, nHeight );
|
|
}
|
|
|
|
|
|
void KTextLayout2::SplitLine( std::vector< std::string > & vecLineList, int nLimitWidth, const std::string& _strOriginal, const char* szFontName, int nFontSize, bool bBold )
|
|
{
|
|
PangoLayout* layout = pango_layout_new( GetPangoContext() );
|
|
|
|
if ( nLimitWidth >= 0 )
|
|
pango_layout_set_width( layout, nLimitWidth * PANGO_SCALE );
|
|
else
|
|
pango_layout_set_width( layout, -1 );
|
|
|
|
pango_layout_set_auto_dir( layout, ENV().GetInt( "layout_auto", true ) );
|
|
|
|
PangoFontDescription *desc;
|
|
|
|
std::string strOriginal = multibyte_to_utf8( _strOriginal );
|
|
|
|
std::string strFont;
|
|
|
|
XStringUtil::Format( strFont, "%s %d", szFontName, nFontSize );
|
|
|
|
desc = pango_font_description_from_string( strFont.c_str() );
|
|
if ( bBold )
|
|
pango_font_description_set_weight( desc, PANGO_WEIGHT_BOLD );
|
|
pango_layout_set_font_description( layout, desc );
|
|
pango_font_description_free( desc );
|
|
|
|
pango_layout_set_text( layout, strOriginal.c_str(), -1 );
|
|
int nLines = pango_layout_get_line_count( layout );
|
|
|
|
PangoLayoutLine* pLine;
|
|
std::string strLine;
|
|
|
|
for ( int i = 0; i < nLines; ++i )
|
|
{
|
|
pLine = pango_layout_get_line_readonly( layout, i );
|
|
|
|
strLine = strOriginal.substr( pLine->start_index, pLine->length );
|
|
vecLineList.push_back( utf8_to_multibyte( strLine ) );
|
|
}
|
|
|
|
g_object_unref( layout );
|
|
}
|
|
|
|
|
|
/// 2011.01.18 - prodongi
|
|
void KTextLayout2::setSpriteScroll(bool scroll, DWORD type, float v, float margin)
|
|
{
|
|
m_spriteScrollInfo.set(scroll, type, v, margin);
|
|
m_prSprite->initScroll(scroll, type, v, margin);
|
|
}
|
|
|
|
/// 2011.02.23 - prodongi
|
|
void KTextLayout2::setSpriteScrollInfo(const KTextLayout2::sSpriteScrollInfo &info)
|
|
{
|
|
m_spriteScrollInfo = info;
|
|
}
|
|
|
|
/// 2011.02.23 - prodongi
|
|
void KTextLayout2::getSpriteScrollInfo(KTextLayout2::sSpriteScrollInfo& info)
|
|
{
|
|
info = m_spriteScrollInfo;
|
|
}
|
|
|
|
/// 2011.02.23 - prodongi
|
|
void KTextLayout2::updateSpriteScrollInfo()
|
|
{
|
|
setSpriteScroll(m_spriteScrollInfo.m_scroll, m_spriteScrollInfo.m_type,
|
|
m_spriteScrollInfo.m_v, m_spriteScrollInfo.m_margin);
|
|
}
|
|
|
|
#endif
|
|
|
|
|