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

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