#include "stdafx.h" #ifdef _COUNTRY_ME_ #include "KTextParser.h" #include "KTextLayout.h" #include "KTextEmoticonRender.h" #include #include "KTextCacheManager.h" #include "KPrimitiveSprite.h" #include "KViewport.h" #include #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 ( ( 0 * 255 + ( 255.0 - bAlpha ) * pxDst.g * pxDst.a / 255 ) / pxFinal.a ); pxFinal.b = static_cast ( ( 74 * 255 + ( 255.0 - bAlpha ) * pxDst.b * pxDst.a / 255 ) / pxFinal.a ); pxFinal.r = static_cast ( (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 ( ( pxSrc.r * 255 + ( 255.0 - pxSrc.a ) * pxDst.a * pxDst.r / 255) / pxFinal.a ); pxFinal.g = static_cast ( ( pxSrc.g * 255 + ( 255.0 - pxSrc.a ) * pxDst.a * pxDst.g / 255) / pxFinal.a ); pxFinal.b = static_cast ( ( 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(&pDstBuf), nDstStride); assert( pDstBuf && "m_spTexture->LockRect(&rcTexRect, reinterpret_cast(&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