DragonNest/Common/EtInterface/EtFontMng.cpp
Cussrro 47f7895977 Revert "修复编码问题"
This reverts commit 9e69c01767.
2024-12-21 10:04:04 +08:00

2476 lines
No EOL
76 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StdAfx.h"
#include "EtSprite.h"
#include "EtFontMng.h"
#include "..\EtCamera.h"
#include "DebugSet.h"
#include "EtResourceMng.h"
#include "EtStdFileIO.h"
#include <shlobj.h>
#include <strsafe.h>
#include "./boost/algorithm/string.hpp"
float CEtFontMng::s_fLinePitchRate = 1.0f;
bool CEtFontMng::s_bUseUniscribe = true;
bool CEtFontMng::s_bUseWordBreak = false;
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
/**/
#define ACCUMLATE_COLOR( ALPHA, RED, GREEN, BLUE, NOWCOLOR, WEIGHT ) \
{ \
ALPHA += ((0xff000000 & NOWCOLOR) >> 24) * WEIGHT; \
RED += ((0x00ff0000 & NOWCOLOR) >> 16) * WEIGHT; \
GREEN += ((0x0000ff00 & NOWCOLOR) >> 8) * WEIGHT; \
BLUE += (0x000000ff & NOWCOLOR) * WEIGHT; \
}
#define BLUR_PROCESS( ORIGIN, BYTEPOS, BLURDIR, Y, X, TEXBUF, PITCH, WIDTH, HEIGHT, WEIGHT ) \
{ \
DWORD dwResultColor = 0; \
int nWeightCount = 0; \
DWORD dwAlpha = 0; \
DWORD dwRed = 0; \
DWORD dwGreen = 0; \
DWORD dwBlue = 0; \
if( BLURDIR[ 0 ] && \
1 <= Y && 1 <= X ) \
{ \
nWeightCount += 1; \
DWORD dwNowColor = *(DWORD*)(&ORIGIN[ BYTEPOS - PITCH - 1*sizeof(DWORD) ]); \
dwResultColor += dwNowColor; \
ACCUMLATE_COLOR( dwAlpha, dwRed, dwGreen, dwBlue, dwNowColor, 1 ); \
} \
if( BLURDIR[ 1 ] && \
1 <= Y ) \
{ \
nWeightCount += 2; \
DWORD dwNowColor = *(DWORD*)(&ORIGIN[ BYTEPOS - PITCH ]); \
dwResultColor += dwNowColor*2; \
ACCUMLATE_COLOR( dwAlpha, dwRed, dwGreen, dwBlue, dwNowColor, 2 ); \
} \
if( BLURDIR[ 2 ] && \
1 <= Y && X < WIDTH-1 ) \
{ \
nWeightCount += 1; \
DWORD dwNowColor = *(DWORD*)(&ORIGIN[ BYTEPOS - PITCH + 1*sizeof(DWORD) ]); \
dwResultColor += dwNowColor; \
ACCUMLATE_COLOR( dwAlpha, dwRed, dwGreen, dwBlue, dwNowColor, 1); \
} \
if( BLURDIR[ 3 ] && \
1 <= X ) \
{ \
nWeightCount += 2; \
DWORD dwNowColor = *(DWORD*)(&ORIGIN[ BYTEPOS - sizeof(DWORD) ]); \
dwResultColor += dwNowColor*2; \
ACCUMLATE_COLOR( dwAlpha, dwRed, dwGreen, dwBlue, dwNowColor, 2 ); \
} \
if( BLURDIR[ 4 ] ) \
{ \
nWeightCount += 4; \
DWORD dwNowColor = *(DWORD*)(&ORIGIN[ BYTEPOS ]); \
dwResultColor += dwNowColor*4; \
ACCUMLATE_COLOR( dwAlpha, dwRed, dwGreen, dwBlue, dwNowColor, 4 ); \
} \
if( BLURDIR[ 5 ] && \
X < WIDTH-1 ) \
{ \
nWeightCount += 2; \
DWORD dwNowColor = *(DWORD*)(&ORIGIN[ BYTEPOS + sizeof(DWORD) ]); \
dwResultColor += dwNowColor*2; \
ACCUMLATE_COLOR( dwAlpha, dwRed, dwGreen, dwBlue, dwNowColor, 2 ); \
} \
if( BLURDIR[ 6 ] && \
Y < HEIGHT-1 && 1 <= X ) \
{ \
nWeightCount += 1; \
DWORD dwNowColor = *(DWORD*)(&ORIGIN[ BYTEPOS + PITCH - 1*sizeof(DWORD) ]); \
dwResultColor += dwNowColor; \
ACCUMLATE_COLOR( dwAlpha, dwRed, dwGreen, dwBlue, dwNowColor, 1 ); \
} \
if( BLURDIR[ 7 ] && \
Y < HEIGHT-1 ) \
{ \
nWeightCount += 2; \
DWORD dwNowColor = *(DWORD*)(&ORIGIN[ BYTEPOS + PITCH ]); \
dwResultColor += dwNowColor*2; \
ACCUMLATE_COLOR( dwAlpha, dwRed, dwGreen, dwBlue, dwNowColor, 2 ); \
} \
if( BLURDIR[ 8 ] && \
Y < HEIGHT-1 && X < WIDTH-1 ) \
{ \
nWeightCount += 1; \
DWORD dwNowColor = *(DWORD*)(&ORIGIN[ BYTEPOS + PITCH + 1*sizeof(DWORD) ]); \
dwResultColor += dwNowColor; \
ACCUMLATE_COLOR( dwAlpha, dwRed, dwGreen, dwBlue, dwNowColor, 1 ); \
} \
if( 0 != nWeightCount ) \
{ \
dwAlpha /= nWeightCount; \
if( 0.0f != WEIGHT ) \
dwResultColor = D3DCOLOR_ARGB( min(DWORD((float)dwAlpha*WEIGHT), 255), 255, 255, 255 ); \
else \
dwResultColor = D3DCOLOR_ARGB( min(dwAlpha*(dwAlpha/50), 255), 255, 255, 255 ); \
*(DWORD*)(&TEXBUF[ BYTEPOS ]) = dwResultColor; \
} \
}
//////////////////////////////////////////////////////////////////////////
#include "ft2build.h"
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_BITMAP_H
#include "freetype/ftsynth.h"
extern bool g_bSkipScene;
static CSyncLock s_Lock;
bool SFontInfo::Load( CStream &stream )
{
DWORD dwVersion;
stream >> dwVersion;
switch( dwVersion )
{
case VERSION:
{
stream.ReadBuffer( szFontName, sizeof(char)*LF_FACESIZE );
stream >> nFontHeight;
stream >> nFontWeight;
stream >> bItalic;
}
break;
default:
ASSERT(0&&"SFontInfo::Load");
CDebugSet::ToLogFile( "SFontInfo::Load, default case!" );
return false;
}
return true;
}
bool SFontInfo::Save( CStream &stream )
{
stream << VERSION;
stream.WriteBuffer( szFontName, sizeof(char)*LF_FACESIZE );
stream << nFontHeight;
stream << nFontWeight;
stream << bItalic;
return true;
}
CEtFontMng::CEtFontMng(void)
: m_nUpdateTerm( 0 )
, m_hOldFont( NULL )
, m_fOriginWidth( 0.0f )
#if defined( PRE_MOD_MINIMIZE_FORCE_BLUR )
, m_bForceBlur( false )
, m_fBlurWeight( 0.6f )
, m_nMinimizeSize( 16 )
#endif // #if defined( PRE_MOD_MINIMIZE_FORCE_BLUR )
{
FT_Error error = FT_Init_FreeType(&m_Library);
if( error ) {
CDebugSet::ToLogFile( "CEtFontMng::Initialize, FT_Init_FreeType the return value is %d", error );
}
}
CEtFontMng::~CEtFontMng(void)
{
if( m_Library ) {
FT_Done_FreeType(m_Library);
m_Library = NULL;
}
}
void CEtFontMng::Initialize( const char *szFileName )
{
CEtUIDialog::CalcDialogScaleByResolution( CEtDevice::GetInstance().Width(), CEtDevice::GetInstance().Height() );
if( !LoadFontSet( szFileName ) )
{
SUIFontSet sUIFontSet[3] =
{
SUIFontSet(0, "Arial", "Arial.ttf", 12, 4, false),
SUIFontSet(1, "Arial", "Arial.ttf", 14, 4, false),
SUIFontSet(2, "Arial", "Arial.ttf", 36, 7, false),
};
int nFontIndex(-1);
for( int i=0; i<3; ++i)
{
m_vecFontSet.push_back( sUIFontSet[i] );
nFontIndex = AddFont( m_vecFontSet[i].strFileName.c_str(), m_vecFontSet[i].strFontName.c_str(), m_vecFontSet[i].nFontHeight, m_vecFontSet[i].nFontWeight, m_vecFontSet[i].bItalic );
m_mapFontIndex.insert( std::make_pair( m_vecFontSet[i].nIndex, nFontIndex ) );
}
}
}
void CEtFontMng::Finalize()
{
ScopeLock<CSyncLock> Lock(s_Lock);
m_vecFontSet.clear();
m_mapFontIndex.clear();
DeleteAllFont();
/*UnregisterAllFont();*/
int i, nSize;
nSize = (int)m_cachedFontList.size();
for( i = 0; i < nSize; i++) {
SAFE_RELEASE_SPTR( m_cachedFontList[i].TextureInfo.hTexture );
}
m_cachedFontList.clear();
std::list< EtTextureHandle >::iterator it = m_texturePool.begin();
for( std::list< EtTextureHandle >::iterator it = m_texturePool.begin(); it != m_texturePool.end(); it++ ) {
SAFE_RELEASE_SPTR( (*it) );
}
m_texturePool.clear();
m_caretInfo.clear();
}
//void CEtFontMng::RegisterFont( const char *pFontName )
//{
// ASSERT(pFontName&&"CEtFontMng::RegisterFont");
//
// SRegisterFontInfo ResterFont;
// DWORD dwFileSize, dwFontCount;
// HANDLE hFontHandle;
// char *pFontData;
//
// CResMngStream Stream( pFontName );
//
// Stream.Seek(0, SEEK_END);
// dwFileSize = Stream.Tell();
// Stream.Seek(0, SEEK_SET);
//
// if ( dwFileSize > 300000000 )
// {
// assert(false);
// return;
// }
//
// pFontData = new char[ dwFileSize ];
// Stream.Read(pFontData, dwFileSize);
// hFontHandle = AddFontMemResourceEx( pFontData, dwFileSize, 0, &dwFontCount );
// delete [] pFontData;
//
// ResterFont.hFontHandle = hFontHandle;
// ResterFont.szFontName = pFontName;
//
// m_vecResiteredFont.push_back( ResterFont );
//}
//
//void CEtFontMng::UnregisterFont( const char *pFontName )
//{
// ASSERT(pFontName&&"CEtFontMng::UnregisterFont");
//
// for( int i = 0; i < ( int )m_vecResiteredFont.size(); i++ )
// {
// if( stricmp( pFontName, m_vecResiteredFont[ i ].szFontName.c_str() ) == 0 )
// {
// RemoveFontMemResourceEx( m_vecResiteredFont[ i ].hFontHandle );
// m_vecResiteredFont.erase( m_vecResiteredFont.begin() + i );
// return;
// }
// }
//}
//
//void CEtFontMng::UnregisterAllFont()
//{
// for( int i = 0; i < ( int )m_vecResiteredFont.size(); i++ )
// {
// RemoveFontMemResourceEx( m_vecResiteredFont[ i ].hFontHandle );
// }
// m_vecResiteredFont.clear();
//}
void CEtFontMng::DeleteAllFont()
{
for( int i = 0; i < ( int )m_vecFont.size(); i++ )
{
FT_Done_Face( m_vecFont[i].Face );
}
m_vecFont.clear();
for( std::map< std::string, std::pair<BYTE*, DWORD> >::iterator it = m_FontMemCache.begin(); it != m_FontMemCache.end(); ++it)
{
SAFE_DELETEA( it->second.first );
}
m_FontMemCache.clear();
if( s_bUseUniscribe )
{
for( int i=0; i<static_cast<int>( m_vecAddFontMemResourceList.size() ); i++ )
{
RemoveFontMemResourceEx( m_vecAddFontMemResourceList[i].hFontHandle );
}
m_vecAddFontMemResourceList.clear();
for( int i=0; i<static_cast<int>( m_vecStFontList.size() ); i++ )
{
if( m_vecStFontList[i].hFont )
DeleteObject( m_vecStFontList[i].hFont );
}
m_vecStFontList.clear();
}
}
void CEtFontMng::GetFontInfo( int &nFontSetIndex, int nFontHeight, SFontInfo &FontInfo )
{
ASSERT(m_vecFont.size()&&"CEtFontMng::GetFontInfo");
ASSERT(nFontSetIndex>=0&&"CEtFontMng::GetFontInfo");
int nFontIndex = GetFontIndex( nFontSetIndex, nFontHeight );
if( nFontIndex < 0 || nFontIndex >= (int)m_vecFont.size() ) {
_ASSERT(0&&"CEtFontMng::GetFontInfo" );
return;
}
FontInfo = m_vecFont[ nFontIndex ];
}
int CEtFontMng::AddFont( const char *pFileName, const char *pFontName, int nFontHeight, int nFontWeight, BOOL bItalic )
{
ASSERT(pFontName&&"CEtFontMng::AddFont");
SFontInfo FontInfo;
FontInfo.nFontHeight = nFontHeight;
FontInfo.nFontWeight = nFontWeight;
FontInfo.bItalic = bItalic;
int nNewFontHeight = int(nFontHeight * CEtUIDialog::GetDialogScale());
if( s_bUseUniscribe )
{
char szChangeFontName[ LF_FACESIZE ] = {0,};
GetTTFLocalFontName( pFileName, szChangeFontName );
strcpy_s( FontInfo.szFontName, LF_FACESIZE, szChangeFontName );
for( int i = 0; i < ( int )m_vecFont.size(); i++ )
{
if( ( m_vecFont[ i ].nFontHeight == nNewFontHeight ) &&
( m_vecFont[ i ].nFontWeight == nFontWeight ) &&
( m_vecFont[ i ].bItalic == bItalic ) &&
( stricmp( m_vecFont[ i ].szFontName, szChangeFontName ) == 0 ) )
{
return i;
}
}
}
else
{
strcpy_s( FontInfo.szFontName, LF_FACESIZE, pFontName );
for( int i = 0; i < ( int )m_vecFont.size(); i++ )
{
if( ( m_vecFont[ i ].nFontHeight == nNewFontHeight ) &&
( m_vecFont[ i ].nFontWeight == nFontWeight ) &&
( m_vecFont[ i ].bItalic == bItalic ) &&
( stricmp( m_vecFont[ i ].szFontName, pFontName ) == 0 ) )
{
return i;
}
}
}
// <20>ý<EFBFBD><C3BD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>Ʈ<EFBFBD><C6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ٲ<EFBFBD><D9B2>ְ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>״<EFBFBD><D7B4><EFBFBD> <20><><EFBFBD><EFBFBD>
char acFontFileName[ MAX_PATH ];
char acFontFileExt[ 32 ];
_splitpath_s( pFileName, NULL, 0, NULL, 0, acFontFileName, MAX_PATH, acFontFileExt, 32 );
const char* pFontPathToLoad = NULL;
char acFontFolder[ MAX_PATH ];
char acFontFolderFullPath[ MAX_PATH ];
SHGetFolderPathA( NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_DEFAULT, acFontFolder );
sprintf_s( acFontFolderFullPath, "%s\\%s%s", acFontFolder, acFontFileName, acFontFileExt );
WIN32_FIND_DATAA Result;
HANDLE hFileFind = FindFirstFileA( acFontFolderFullPath, &Result );
bool bExistInSystemFontFolder = false;
if( INVALID_HANDLE_VALUE == hFileFind )
{
pFontPathToLoad = pFileName;
}
else
{
bExistInSystemFontFolder = true;
pFontPathToLoad = acFontFolderFullPath;
FindClose( hFileFind );
}
DWORD dwQuality(DEFAULT_QUALITY);
int nOsType = GetOSVersionType();
switch( nOsType )
{
case 1: // 1 : Windows 95
case 2: // 2 : Windows 98, 98SE
case 4: dwQuality = 4; break; // 4 : Windows NT, DEFAULT_QUALITY
case 3: // 3 : Windows ME
case 5: dwQuality = 5; break; // 5 : Windows 2000, CLEARTYPE_QUALITY
case 6: // 6 : Windows XP
case 7: // 7 : Windows Server 2003
case 8: dwQuality = 6; break; // 8 : Windows Vista, CLEARTYPE_NATURAL_QUALITY
}
FontInfo.nFontHeight = nNewFontHeight;
DWORD dwFileSize = 0;
if( m_FontMemCache.count( pFontPathToLoad ) != 0) {
FontInfo.pMemFont = m_FontMemCache[ pFontPathToLoad ].first;
dwFileSize = m_FontMemCache[ pFontPathToLoad ].second;
}
else {
if( !bExistInSystemFontFolder )
{
CResMngStream Stream( pFontPathToLoad );
if( !Stream.IsValid() ) {
_ASSERT( !"<EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD> <20>б<EFBFBD> <20><><EFBFBD><EFBFBD>!" );
CDebugSet::ToLogFile( "CEtFontMng::AddFont, Font file load fail (%s)", pFontPathToLoad );
return -1;
}
Stream.Seek(0, SEEK_END);
dwFileSize = Stream.Tell();
Stream.Seek(0, SEEK_SET);
FontInfo.pMemFont = new BYTE[ dwFileSize ];
Stream.Read(FontInfo.pMemFont, dwFileSize);
m_FontMemCache[ pFontPathToLoad ].first = FontInfo.pMemFont;
m_FontMemCache[ pFontPathToLoad ].second = dwFileSize;
}
else
{
CEtStdFileIO Stream;
if( Stream.Open( pFontPathToLoad, CEtStdFileIO::ET_READ ) )
{
Stream.Seek( 0, CEtStdFileIO::ET_SEEK_END );
dwFileSize = Stream.Tell();
Stream.Seek( 0, CEtStdFileIO::ET_SEEK_BEGIN );
FontInfo.pMemFont = new BYTE[ dwFileSize ];
Stream.Read(FontInfo.pMemFont, dwFileSize);
m_FontMemCache[ pFontPathToLoad ].first = FontInfo.pMemFont;
m_FontMemCache[ pFontPathToLoad ].second = dwFileSize;
// Close() <20><> <20>ı<EFBFBD><C4B1>ڿ<EFBFBD> <20>ֱ<EFBFBD><D6B1><EFBFBD>..
}
else
{
_ASSERT( !"<EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD> <20>б<EFBFBD> <20><><EFBFBD><EFBFBD>!" );
CDebugSet::ToLogFile( "CEtFontMng::AddFont, Font file load fail (%s)", pFontPathToLoad );
return -1;
}
}
}
FT_Error error = FT_New_Memory_Face(m_Library, FontInfo.pMemFont, dwFileSize, 0, &FontInfo.Face);
if( error )
{
CDebugSet::ToLogFile( "CEtFontMng::AddFont, FT_New_Face the return value is %d", error );
}
//HDC hDC = FontInfo.pFont->GetDC();
//HDC hDC = ::GetDC( GetEtDevice()->GetHWnd() );
//int nDPI = 72 * 72 / GetDeviceCaps(hDC, LOGPIXELSY);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>⺻ 96dpi <20>ػ󵵸<D8BB> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//int nXDPI = GetDeviceCaps( hDC, LOGPIXELSX );
//int nYDPI = GetDeviceCaps( hDC, LOGPIXELSY );
//FT_Set_Char_Size( FontInfo.Face, (nNewFontHeight) << 6, 0, nXDPI, nYDPI);
FT_Set_Pixel_Sizes( FontInfo.Face, nNewFontHeight, nNewFontHeight );
if( s_bUseUniscribe )
{
if( !IsExistAddFontResourceList( FontInfo ) )
{
DWORD dwFonts;
HANDLE hFontHandle = AddFontMemResourceEx( FontInfo.pMemFont, dwFileSize, NULL, &dwFonts );
if( hFontHandle )
{
SAddFontMemResource sAddFontMemResource;
strcpy_s( sAddFontMemResource.szFontName, LF_FACESIZE, FontInfo.szFontName );
sAddFontMemResource.hFontHandle = hFontHandle;
m_vecAddFontMemResourceList.push_back( sAddFontMemResource );
}
else
{
_ASSERT( !"<EFBFBD><EFBFBD>Ʈ <20><><EFBFBD>ҽ<EFBFBD> <20>߰<EFBFBD> <20><><EFBFBD><EFBFBD>!" );
CDebugSet::ToLogFile( "CEtFontMng::AddFont, AddFontMemResourceEx Fail! (%s)", pFontPathToLoad );
return -1;
}
}
HFONT hFont = CreateFontA( FontInfo.nFontHeight, 0, 0, 0, FW_NORMAL, FALSE, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, dwQuality, FF_DONTCARE, FontInfo.szFontName );
if( hFont )
{
SFontInfoHandle sFontInfoHandle;
sFontInfoHandle.nFontHeight = FontInfo.nFontHeight;
strcpy_s( sFontInfoHandle.szFontName, LF_FACESIZE, FontInfo.szFontName );
sFontInfoHandle.hFont = hFont;
m_vecStFontList.push_back( sFontInfoHandle );
}
}
m_vecFont.push_back( FontInfo );
return ( int )m_vecFont.size() - 1;
}
SCachedFont* CEtFontMng::GetCachedFontTexture( LPCWSTR szText, float fWidth,
SFontDrawEffectInfo& FontEffectInfo, int nFontIndex )
{
ScopeLock<CSyncLock> Lock(s_Lock);
SCachedFont* pResult = NULL;
int i, nSize;
nSize = (int)m_cachedFontList.size();
for( i = 0; i < nSize; i++)
{
SCachedFont& CachedFont = m_cachedFontList[i];
if( CachedFont.nFontIndex == nFontIndex &&
CachedFont.fWidth == fWidth &&
CachedFont.FontEffectInfo.nDrawType == FontEffectInfo.nDrawType &&
CachedFont.FontEffectInfo.fGlobalBlurAlphaWeight == FontEffectInfo.fGlobalBlurAlphaWeight &&
wcscmp(CachedFont.szText.c_str(), szText) == 0 )
{
if( SFontDrawEffectInfo::NORMAL != FontEffectInfo.nDrawType )
{
if( (CachedFont.FontEffectInfo.nDrawType != FontEffectInfo.nDrawType) ||
(CachedFont.FontEffectInfo.nWeight != FontEffectInfo.nWeight) ||
(CachedFont.FontEffectInfo.fAlphaWeight != FontEffectInfo.fAlphaWeight) )//||
/*( (CachedFont.FontEffectInfo.dwFontColor&0x00ffffff) != (FontEffectInfo.dwFontColor&0x00ffffff) ) ||
( (CachedFont.FontEffectInfo.dwEffectColor&0x00ffffff) != (FontEffectInfo.dwEffectColor&0x00ffffff) ) )*/
continue;
}
CachedFont.nLastUseTick = GetTickCount();
pResult = &CachedFont;
break;
}
}
return pResult;
}
//SCachedFont* CEtFontMng::GetCachedFontTextureJustSameText( LPCWSTR szText, int nFontIndex )
//{
// ScopeLock<CSyncLock> Lock(s_Lock);
//
// SCachedFont* pResult = NULL;
//
// int i, nSize;
// nSize = (int)m_cachedFontList.size();
// for( i = 0; i < nSize; i++)
// {
// SCachedFont& CachedFont = m_cachedFontList[i];
// if( CachedFont.nFontIndex == nFontIndex &&
// wcscmp(CachedFont.szText.c_str(), szText) == 0 )
// {
// CachedFont.nLastUseTick = GetTickCount();
// pResult = &CachedFont;
// break;
// }
// }
// return pResult;
//}
void CEtFontMng::UpdateFontCache( bool bRemoveCache )
{
if( bRemoveCache && ((m_nUpdateTerm++) % 100 ) == 0 ) {
int nCurrTick = GetTickCount();
ScopeLock<CSyncLock> Lock(s_Lock);
for( std::vector<SCachedFont>::iterator it = m_cachedFontList.begin(); it != m_cachedFontList.end(); ) {
if( it->nLastUseTick + 2000 < nCurrTick ) {
m_texturePool.push_back( it->TextureInfo.hTexture );
if( m_texturePool.size() > 300 ) {
EtTextureHandle hTexture = m_texturePool.front();
SAFE_RELEASE_SPTR( hTexture );
m_texturePool.pop_front();
}
SCaretKey CaretKey;
CaretKey.szText = it->szText;
CaretKey.nFontIndex = it->nFontIndex;
m_caretInfo.erase( CaretKey );
// bool bAlreadyExistCaret = (m_caretInfo.find( CaretKey ) != m_caretInfo.end() );
it = m_cachedFontList.erase( it );
}
else {
++it;
}
}
}
}
void CEtFontMng::FlushFontCache()
{
std::list< EtTextureHandle >::iterator it = m_texturePool.begin();
for( std::list< EtTextureHandle >::iterator it = m_texturePool.begin(); it != m_texturePool.end(); it++ ) {
SAFE_RELEASE_SPTR( (*it) );
}
m_texturePool.clear();
int nSize = (int)m_cachedFontList.size();
for( int i = 0; i < nSize; i++) {
SAFE_RELEASE_SPTR( m_cachedFontList[i].TextureInfo.hTexture );
SCaretKey CaretKey;
CaretKey.szText = m_cachedFontList[i].szText;
CaretKey.nFontIndex = m_cachedFontList[i].nFontIndex;
m_caretInfo.erase( CaretKey );
}
m_cachedFontList.clear();
// SAFE_RELEASE_SPTRVEC( m_texturePool );
/*
for( DWORD i=0; i<m_texturePool.size(); i++ ) {
SAFE_RELEASE_SPTR( m_texturePool[i] );
}
m_texturePool.clear();
*/
}
int CEtFontMng::GetCachedCharAdvanceX( FT_Face Face, SFontInfo& FontInfo, wchar_t ch, bool bBold, int iNowAdvance )
{
ScopeLock<CSyncLock> Lock(s_Lock);
int nAdvanceX = 0;
if( false == bBold )
{
map<wchar_t, int>::iterator iter = FontInfo.mapAdvanceX.find( (wchar_t)ch );
if( FontInfo.mapAdvanceX.end() != iter )
nAdvanceX = iter->second;
}
else
{
map<wchar_t, int>::iterator iter = FontInfo.mapBoldAdvanceX.find( (wchar_t)ch );
if( FontInfo.mapBoldAdvanceX.end() != iter )
nAdvanceX = iter->second;
}
bool bCantCaching = false;
if( 0 == nAdvanceX )
{
FT_Error err = FT_Load_Char( Face, ch, FT_LOAD_RENDER|/*FT_LOAD_NO_BITMAP|*/FT_LOAD_FORCE_AUTOHINT );
if( err )
return -1;
if( bBold )
FT_GlyphSlot_Embolden( Face->glyph );
nAdvanceX = (Face->glyph->advance.x >> 6);
if( iNowAdvance + Face->glyph->bitmap_left < 0 )
{
nAdvanceX += -(iNowAdvance + Face->glyph->bitmap_left);
bCantCaching = true;
}
if( false == bCantCaching )
{
if( false == bBold )
FontInfo.mapAdvanceX.insert( make_pair((wchar_t)ch, nAdvanceX) );
else
FontInfo.mapBoldAdvanceX.insert( make_pair((wchar_t)ch, nAdvanceX) );
}
}
return nAdvanceX;
}
void CEtFontMng::AccumulateColor( DWORD& dwAlpha, DWORD& dwRed, DWORD& dwGreen, DWORD& dwBlue, DWORD& dwNowColor, int iWeight )
{
dwAlpha += ((0xff000000 & dwNowColor) >> 24) * iWeight;
dwRed += ((0x00ff0000 & dwNowColor) >> 16) * iWeight;
dwGreen += ((0x0000ff00 & dwNowColor) >> 8) * iWeight;
dwBlue += (0x000000ff & dwNowColor) * iWeight;
}
void CEtFontMng::BlurProcess( BYTE* pOriginalBuffer, int nBytePos, bool* pabBlurDir, int nY, int nX, BYTE* pTextureBuffer,
int nPitch, int nTexelWidth, int nTexelHeight, float fAlphaWeight )
{
DWORD dwResultColor = 0;
int nWeightCount = 0;
// <20><><EFBFBD>İ<EFBFBD><C4B0><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.. <20>ϴ<EFBFBD> Ȯ<><C8AE> <20><> <20>غ<EFBFBD><D8BA><EFBFBD>
//DWORD dwNowColor = *(DWORD*)(&pOriginalBuffer[ nBytePos ]);
//DWORD dwAlpha = 0xff000000 & *(DWORD*)(&pTextureBuffer[ nBytePos ]);
DWORD dwAlpha = 0;
DWORD dwRed = 0;
DWORD dwGreen = 0;
DWORD dwBlue = 0;
// <20>»<EFBFBD>
if( pabBlurDir[ 0 ] &&
1 <= nY && 1 <= nX )
{
nWeightCount += 1;
DWORD dwNowColor = *(DWORD*)(&pOriginalBuffer[ nBytePos - nPitch - 1*sizeof(DWORD) ]);
dwResultColor += dwNowColor;
AccumulateColor( dwAlpha, dwRed, dwGreen, dwBlue, dwNowColor, 1 );
}
// <20><>
if( pabBlurDir[ 1 ] &&
1 <= nY )
{
nWeightCount += 2;
DWORD dwNowColor = *(DWORD*)(&pOriginalBuffer[ nBytePos - nPitch ]);
dwResultColor += dwNowColor*2;
AccumulateColor( dwAlpha, dwRed, dwGreen, dwBlue, dwNowColor, 2 );
}
// <20><><EFBFBD><EFBFBD>
if( pabBlurDir[ 2 ] &&
1 <= nY && nX < nTexelWidth-1 )
{
nWeightCount += 1;
DWORD dwNowColor = *(DWORD*)(&pOriginalBuffer[ nBytePos - nPitch + 1*sizeof(DWORD) ]);
dwResultColor += dwNowColor;
AccumulateColor( dwAlpha, dwRed, dwGreen, dwBlue, dwNowColor, 1);
}
// <20><>
if( pabBlurDir[ 3 ] &&
1 <= nX )
{
nWeightCount += 2;
DWORD dwNowColor = *(DWORD*)(&pOriginalBuffer[ nBytePos - sizeof(DWORD) ]);
dwResultColor += dwNowColor*2;
AccumulateColor( dwAlpha, dwRed, dwGreen, dwBlue, dwNowColor, 2 );
}
// <20><><EFBFBD><EFBFBD> <20>ؼ<EFBFBD>
if( pabBlurDir[ 4 ] )
{
nWeightCount += 4;
DWORD dwNowColor = *(DWORD*)(&pOriginalBuffer[ nBytePos ]);
dwResultColor += dwNowColor*4;
AccumulateColor( dwAlpha, dwRed, dwGreen, dwBlue, dwNowColor, 4 );
}
// <20><>
if( pabBlurDir[ 5 ] &&
nX < nTexelWidth-1 )
{
nWeightCount += 2;
DWORD dwNowColor = *(DWORD*)(&pOriginalBuffer[ nBytePos + sizeof(DWORD) ]);
dwResultColor += dwNowColor*2;
AccumulateColor( dwAlpha, dwRed, dwGreen, dwBlue, dwNowColor, 2 );
}
// <20><><EFBFBD><EFBFBD>
if( pabBlurDir[ 6 ] &&
nY < nTexelHeight-1 && 1 <= nX )
{
nWeightCount += 1;
DWORD dwNowColor = *(DWORD*)(&pOriginalBuffer[ nBytePos + nPitch - 1*sizeof(DWORD) ]);
dwResultColor += dwNowColor;
AccumulateColor( dwAlpha, dwRed, dwGreen, dwBlue, dwNowColor, 1 );
}
// <20><>
if( pabBlurDir[ 7 ] &&
nY < nTexelHeight-1 )
{
nWeightCount += 2;
DWORD dwNowColor = *(DWORD*)(&pOriginalBuffer[ nBytePos + nPitch ]);
dwResultColor += dwNowColor*2;
AccumulateColor( dwAlpha, dwRed, dwGreen, dwBlue, dwNowColor, 2 );
}
// <20><><EFBFBD><EFBFBD>
if( pabBlurDir[ 8 ] &&
nY < nTexelHeight-1 && nX < nTexelWidth-1 )
{
nWeightCount += 1;
DWORD dwNowColor = *(DWORD*)(&pOriginalBuffer[ nBytePos + nPitch + 1*sizeof(DWORD) ]);
dwResultColor += dwNowColor;
AccumulateColor( dwAlpha, dwRed, dwGreen, dwBlue, dwNowColor, 1 );
}
if( 0 != nWeightCount )
{
dwAlpha /= nWeightCount;
if( 0.0f != fAlphaWeight )
dwResultColor = D3DCOLOR_ARGB( min(DWORD((float)dwAlpha*fAlphaWeight), 255), 255, 255, 255 );
else
dwResultColor = D3DCOLOR_ARGB( min(dwAlpha*(dwAlpha/50), 255), 255, 255, 255 );
*(DWORD*)(&pTextureBuffer[ nBytePos ]) = dwResultColor;
}
//if( 0 != nWeightCount )
//{
// dwAlpha /= nWeightCount;
// if( 0.0f != fAlphaWeight )
// dwResultColor = D3DCOLOR_ARGB( min(DWORD((float)dwAlpha*fAlphaWeight), 255), 255, 255, 255 );
// else
// dwResultColor = D3DCOLOR_ARGB( min(dwAlpha*(dwAlpha/50), 255), 255, 255, 255 );
// dwResultColor |= (dwColor & 0x00ffffff);
// //dwResultColor = D3DCOLOR_ARGB( min(dwAlpha*(dwAlpha/50), 255), dwRed/nWeightCount, dwGreen/nWeightCount, dwBlue/nWeightCount );
// //dwResultColor = D3DCOLOR_ARGB( min(dwAlpha, 255), dwRed/nWeightCount, dwGreen/nWeightCount, dwBlue/nWeightCount );
// //dwResultColor /= nWeightCount;
// *(DWORD*)(&pTextureBuffer[ nBytePos ]) = dwResultColor;
//}
}
void CEtFontMng::Blur( BYTE* pTextureBuffer, BYTE* pOriginalBuffer, bool* pabBlurDir,
float fAlphaWeight, int nPitch, int nTexelWidth, int nTexelHeight, int nTextTexelWidth, int nTextTexelHeight, bool bReverseLoop /*= false */ )
{
int nEndBytePos = nTexelHeight*nPitch;
if( false == bReverseLoop )
{
for( int nY = 0; nY < nTexelHeight; ++nY )
{
for( int nX = 0; nX < nTexelWidth; ++nX )
{
int nBytePos = nY*nPitch + nX*sizeof(DWORD);
if( nBytePos < nEndBytePos )
{
BLUR_PROCESS( pOriginalBuffer, nBytePos, pabBlurDir, nY, nX, pTextureBuffer, nPitch, nTexelWidth, nTexelHeight, fAlphaWeight );
//BlurProcess( pOriginalBuffer, nBytePos, pabBlurDir, nY, nX, pTextureBuffer, nPitch, nTexelWidth, nTexelHeight, fAlphaWeight );
}
}
}
}
else
{
for( int nY = nTexelHeight-1; nY > 0; --nY )
{
for( int nX = nTexelWidth; nX > 0; --nX )
{
int nBytePos = nY*nPitch + nX*sizeof(DWORD);
if( nBytePos < nEndBytePos )
{
BLUR_PROCESS(pOriginalBuffer, nBytePos, pabBlurDir, nY, nX, pTextureBuffer, nPitch, nTexelWidth, nTexelHeight, fAlphaWeight);
//BlurProcess(pOriginalBuffer, nBytePos, pabBlurDir, nY, nX, pTextureBuffer, nPitch, nTexelWidth, nTexelHeight, fAlphaWeight);
}
}
}
}
}
SFontTextureInfo CEtFontMng::GetFontTexture( int nFontIndex, LPCWSTR szText, float fWidth, DWORD dwFontFormat,
SFontDrawEffectInfo& Info, bool bRemoveCache /*= true */ )
{
ScopeLock<CSyncLock> Lock(s_Lock);
SCaretKey CaretKey;
CaretKey.szText = szText;
CaretKey.nFontIndex = nFontIndex;
bool bAlreadyExistCaret = ( m_caretInfo.find( CaretKey ) != m_caretInfo.end() );
FT_Face Face = m_vecFont[ nFontIndex ].Face;
bool bBold = m_vecFont[ nFontIndex ].nFontWeight*100 >= FW_BOLD;
SCachedFont* pCachedTextureInfo = GetCachedFontTexture( szText, fWidth, Info, nFontIndex );
if( pCachedTextureInfo )
return pCachedTextureInfo->TextureInfo;
SFontInfo& FontInfo = m_vecFont.at( nFontIndex );
SCachedFont fkInfo;
wstring strText = szText;
// <20>ʿ<EFBFBD><CABF><EFBFBD> <20>ؽ<EFBFBD><D8BD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><20><><EFBFBD><EFBFBD>
int nHeightPerLine = (int)floorf((float)Face->size->metrics.height / 64.0f); // <20>ݿø<DDBF> ó<><C3B3>
// <20><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
nHeightPerLine = int(nHeightPerLine * s_fLinePitchRate);
int nLineGap = nHeightPerLine - (Face->size->metrics.y_ppem);
vector<wstring> vecStrLine;
vector<int> vecWidthList;
int nNumLine = WordBreak( strText, CaretKey, bAlreadyExistCaret, Face, bBold, FontInfo, fWidth, vecStrLine, vecWidthList );
if( nNumLine == -1 )
return fkInfo.TextureInfo;
int nLongestWidth = 0;
for( int nLine=0; nLine<nNumLine; ++nLine )
{
int nWidth = vecWidthList.at( nLine );
if( nLongestWidth < nWidth )
nLongestWidth = nWidth;
}
int nWholeHeight = nHeightPerLine * nNumLine;
int nNeedWidth = nLongestWidth;
int nNeedHeight = nWholeHeight;
if( SFontDrawEffectInfo::NORMAL != Info.nDrawType )
{
nNeedWidth += Info.nWeight*2;
nNeedHeight += Info.nWeight*2;
}
if( s_bUseUniscribe )
nNeedHeight += (int)( UPPER_PADDING_PIXEL );
int nBufferTextureWidth = CEtTexture::CalcTextureSize( nNeedWidth );
int nBufferTextureHeight = CEtTexture::CalcTextureSize( nNeedHeight );
EtTextureHandle hFontTexture;
std::list<EtTextureHandle>::iterator it = m_texturePool.begin();
while( it != m_texturePool.end() ) {
EtTextureHandle hTexture = *it;
if( hTexture &&
hTexture->Width() == nBufferTextureWidth &&
hTexture->Height() == nBufferTextureHeight ) {
hFontTexture = hTexture;
it = m_texturePool.erase( it );
break;
}
++it;
}
if( !hFontTexture ) {
if( GetEtDevice()->IsAutoGenMipmap() ) {
hFontTexture = CEtTexture::CreateNormalTexture( nBufferTextureWidth, nBufferTextureHeight, FMT_A8R8G8B8, USAGE_AUTOGENMIPMAP, POOL_MANAGED, 0 );
if( !hFontTexture->GetTexturePtr() ) {
SAFE_RELEASE_SPTR( hFontTexture );
hFontTexture = CEtTexture::CreateNormalTexture( nBufferTextureWidth, nBufferTextureHeight, FMT_A8R8G8B8, USAGE_DEFAULT, POOL_MANAGED );
}
}
else {
hFontTexture = CEtTexture::CreateNormalTexture( nBufferTextureWidth, nBufferTextureHeight, FMT_A8R8G8B8, USAGE_DEFAULT, POOL_MANAGED );
}
}
/*
else {
hFontTexture->ChangeFormat( FMT_A8R8G8B8 );
}
*/
int nFontTexturePitch = 0;
DWORD *pPtr = (DWORD*)hFontTexture->Lock( nFontTexturePitch, true );
if( pPtr ) {
BYTE *pFontTextureBuffer = (BYTE*)pPtr;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ü<EFBFBD><C3BC> <20><><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD>.
for( int y = 0; y < nBufferTextureHeight; y++) {
memset( pFontTextureBuffer + y * nFontTexturePitch, 0x0, nBufferTextureWidth*sizeof(DWORD) );
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ؽ<EFBFBD><D8BD>Ŀ<EFBFBD> <20><>Ʈ <20><>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD>׿<EFBFBD>
/*
DWORD* adwTest = new DWORD[ nBufferTextureWidth*nBufferTextureHeight ];
memset( adwTest, 200, nBufferTextureWidth*nBufferTextureHeight*sizeof(DWORD) );
memcpy( pPtr, adwTest, nBufferTextureWidth*nBufferTextureHeight*sizeof(DWORD) );
delete [] adwTest;
DWORD dwRed = ((Info.dwFontColor) & 0x00ff0000) >> 16;
DWORD dwGreen = ((Info.dwFontColor) & 0x00000ff00) >> 8;
DWORD dwBlue = Info.dwFontColor & 0x000000ff;
*/
int nBaseLinePos = int((float)(nHeightPerLine-nLineGap) * 0.9f);
int nPenX = 0, nPenY = 0;
//bool bHasKerningInfo = FT_HAS_GETKERNING( Face );
for( int nLine = 0; nLine < nNumLine; ++nLine )
{
// <20><><EFBFBD><EFBFBD> <20><> Pen <20><>ġ <20><><EFBFBD><EFBFBD>
int nXCenterOffset = 0;
if( dwFontFormat & DT_CENTER )
nXCenterOffset = (nLongestWidth - vecWidthList.at(nLine)) / 2;
nPenX = 0;
nPenY = ((nHeightPerLine*nLine + nBaseLinePos) << 6);
//if( SFontDrawEffectInfo::NORMAL != Info.nDrawType )
//{
// nPenX += (Info.nWeight << 6);
// nPenY += (Info.nWeight << 6);
//}
int iEffectXOffset = 0;
int iEffectYOffset = 0;
if( SFontDrawEffectInfo::NORMAL != Info.nDrawType )
{
iEffectXOffset += Info.nWeight;
iEffectYOffset += Info.nWeight;
}
int nCharIndex = 0;
int iFTBitmapLeftOffset = 0; // <20>۸<EFBFBD><DBB8><EFBFBD><EFBFBD><EFBFBD> bitmap_left <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><20>־ üũ<C3BC><C5A9>. (daum_regular <20><>Ʈ..)
int iRenderXOffset = 0;
wstring& strLine = vecStrLine.at(nLine);
int nStrLength = (int)strLine.length();
if( s_bUseUniscribe )
{
vector<WORD> vecGlyph;
vector<GOFFSET> vecGOffset;
int nGlyphCount = GetGlyphGOffset( m_vecFont[ nFontIndex ], strLine, vecGlyph, vecGOffset );
nPenX = 0;
nPenY = ((nHeightPerLine*nLine + nBaseLinePos) << 6);
for( int i=0; i<nGlyphCount; i++ )
{
FT_Glyph Glyph;
if( FT_Load_Glyph( Face, vecGlyph[i], FT_LOAD_DEFAULT ) )
continue;
if( bBold )
FT_GlyphSlot_Embolden( Face->glyph );
// Load the glyph data into our local array.
if( FT_Get_Glyph( Face->glyph, &Glyph ) )
continue;
// Convert the glyph to bitmap form.
FT_Glyph_To_Bitmap( &Glyph, FT_RENDER_MODE_NORMAL, NULL, TRUE );
FT_Bitmap &Bitmap = ((FT_BitmapGlyph)Glyph)->bitmap;
int nGlyphBitmapWidth = Bitmap.width;
int nGlyphBitmapHeight = Bitmap.rows;
for( int nY = 0; nY < nGlyphBitmapHeight; ++nY )
{
for( int nX = 0; nX < nGlyphBitmapWidth; ++nX )
{
int nColor = Bitmap.buffer[ nY*nGlyphBitmapWidth + nX ];
int nBytePos = ((nPenY >> 6) - vecGOffset[i].dv - ((FT_BitmapGlyph)Glyph)->top + nY + (int)( UPPER_PADDING_PIXEL ) + iEffectYOffset) * nFontTexturePitch +
((nPenX >> 6) + vecGOffset[i].du + ((FT_BitmapGlyph)Glyph)->left + nX + nXCenterOffset + iEffectXOffset + iRenderXOffset) * sizeof(DWORD);
/*ASSERT( 0 <= nBytePos );*/
if( nColor > 0 && 0 <= nBytePos && nBytePos <= int(nBufferTextureWidth*nBufferTextureHeight*sizeof(DWORD)) )
{
BYTE* pTexel = pFontTextureBuffer + nBytePos;
*(DWORD*)pTexel = D3DCOLOR_ARGB( nColor, 255, 255, 255 );
}
}
}
nPenX += Face->glyph->advance.x;
nPenY += Face->glyph->advance.y;
FT_Done_Glyph( Glyph );
}
vecGlyph.clear();
vecGOffset.clear();
}
else
{
nPenX = 0;
nPenY = ((nHeightPerLine*nLine + nBaseLinePos) << 6);
for( nCharIndex = 0; nCharIndex < nStrLength; ++nCharIndex )
{
wchar_t Char = strLine.at( nCharIndex );
FT_Error err = FT_Load_Char( Face, Char, FT_LOAD_RENDER|/*FT_LOAD_NO_BITMAP|*/FT_LOAD_FORCE_AUTOHINT );
if( err )
continue;
if( bBold )
FT_GlyphSlot_Embolden( Face->glyph );
int nGlyphBitmapWidth = Face->glyph->bitmap.width;
int nGlyphBitmapHeight = Face->glyph->bitmap.rows;
for( int nY = 0; nY < nGlyphBitmapHeight; ++nY )
{
for( int nX = 0; nX < nGlyphBitmapWidth; ++nX )
{
int nColor = Face->glyph->bitmap.buffer[ nY*nGlyphBitmapWidth + nX ];
int nBytePos = ((nPenY >> 6) - Face->glyph->bitmap_top + nY + iEffectYOffset)*nFontTexturePitch + \
((nPenX >> 6) + Face->glyph->bitmap_left + nX + nXCenterOffset /*- iFTBitmapLeftOffset*/ + iEffectXOffset + iRenderXOffset)*sizeof(DWORD);
/*ASSERT( 0 <= nBytePos );*/
if( nColor > 0 && 0 <= nBytePos && nBytePos <= int(nBufferTextureWidth*nBufferTextureHeight*sizeof(DWORD)) )
{
BYTE* pTexel = pFontTextureBuffer + nBytePos;
//*(DWORD*)pTexel = D3DCOLOR_ARGB( nColor, nColor, nColor, nColor );
//if( SFontDrawEffectInfo::NORMAL != Info.nDrawType )
//{
//if( 255 == nColor )
// *(DWORD*)pTexel = D3DCOLOR_ARGB( z255, nColor, nColor, nColor );
//else
*(DWORD*)pTexel = D3DCOLOR_ARGB( nColor, 255, 255, 255 );
//*(DWORD*)pTexel = D3DCOLOR_ARGB( 255, nColor, nColor, nColor );
//}
//else
//{
// if( 255 == nColor )
// *(DWORD*)pTexel = D3DCOLOR_ARGB( DWORD((float)255*fFontAlpha), dwRed, dwGreen, dwBlue);
// else
// *(DWORD*)pTexel = D3DCOLOR_ARGB( DWORD((float)nColor*fFontAlpha), dwRed, dwGreen, dwBlue );
//}
}
}
}
nPenX += Face->glyph->advance.x;
nPenY += Face->glyph->advance.y;
}
}
}
// <20><>Ʈ <20><><EFBFBD><EFBFBD> Ÿ<>Կ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ó<EFBFBD><C3B3>
if( /*0.0f != Info.fGlobalBlurAlphaWeight || */
SFontDrawEffectInfo::NORMAL != Info.nDrawType )
{
BYTE* apCopyBuffer = new BYTE[nBufferTextureHeight*nFontTexturePitch];
bool abDirection[ 9 ];
ZeroMemory( abDirection, sizeof(abDirection) );
//if( SFontDrawEffectInfo::NORMAL == Info.nDrawType )
//{
// // <20><><EFBFBD><EFBFBD> 2<><32><EFBFBD><20><><EFBFBD>͸<EFBFBD>
// abDirection[ 1 ] /*= abDirection[ 3 ]*/ = abDirection[ 4 ] /*= abDirection[ 5 ]*/ = abDirection[ 7 ] = true;
// memcpy( apCopyBuffer, pFontTextureBuffer, nBufferTextureHeight*nFontTexturePitch );
// Blur( pFontTextureBuffer, apCopyBuffer, abDirection, Info.fGlobalBlurAlphaWeight,
// nFontTexturePitch, nBufferTextureWidth, nBufferTextureHeight, nLongestWidth, nWholeHeight-nLineGap+1, false );
//}
//else
{
float fAlphaWeight = Info.fAlphaWeight;
bool bReverseLoop = false;
switch( Info.nDrawType )
{
case SFontDrawEffectInfo::SHADOW:
{
// <20>»<EFBFBD> <20>ȼ<EFBFBD><C8BC><20><><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD>ǵ<EFBFBD><C7B5><EFBFBD> <20>Ѵ<EFBFBD>.
abDirection[ 0 ] = abDirection[ 1 ] = abDirection[ 2 ] = abDirection[ 3 ] = abDirection[ 4 ] = true;
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>̴<EFBFBD> <20><><EFBFBD><20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>޴´<DEB4>.
bReverseLoop = true;
}
break;
case SFontDrawEffectInfo::STROKE:
{
memset( abDirection, true, sizeof(abDirection) );
// STROKE <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʴ´<CAB4>.
fAlphaWeight = 0.0f; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ġ<EFBFBD><C4A1> 0 <20≯<EFBFBD> <20>ؽ<EFBFBD><D8BD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>.
}
break;
case SFontDrawEffectInfo::GLOW:
{
memset( abDirection, true, sizeof(abDirection) );
}
break;
}
for( int i=0; i<Info.nWeight; ++i )
{
memcpy( apCopyBuffer, pFontTextureBuffer, nBufferTextureHeight*nFontTexturePitch );
Blur( pFontTextureBuffer, apCopyBuffer, abDirection, fAlphaWeight,
nFontTexturePitch, nBufferTextureWidth, nBufferTextureHeight, nLongestWidth, nWholeHeight-nLineGap+1, bReverseLoop );
}
}
delete [] apCopyBuffer;
}
hFontTexture->Unlock();
}
/*
if( hFontTexture ) {
hFontTexture->ChangeFormat( FMT_DXT5 );
}
*/
fkInfo.szText = szText;
fkInfo.nFontIndex = nFontIndex;
fkInfo.bBold = bBold;
fkInfo.TextureInfo.hTexture = hFontTexture;
fkInfo.TextureInfo.Width = nLongestWidth;
fkInfo.TextureInfo.Height = nWholeHeight-nLineGap; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>̴<EFBFBD> <20>̱۶<CCB1><DBB6><EFBFBD><EFBFBD>̴<EFBFBD> metric.height <20><> <20>ִ<EFBFBD> <20><20>ٰ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEBFA1> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ֱ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ΰ<EFBFBD><CEB0><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
fkInfo.FontEffectInfo = Info;
fkInfo.fWidth = fWidth;
fkInfo.nLastUseTick = GetTickCount();
m_cachedFontList.push_back( fkInfo );
if( !bAlreadyExistCaret && 1 == nNumLine ) {
m_caretInfo[ CaretKey ].nHeight = fkInfo.TextureInfo.Height;
}
UpdateFontCache( bRemoveCache );
return fkInfo.TextureInfo;
}
void CEtFontMng::GetBasicFontTextureInfo(SFontTextureInfo& result, int nFontSetIndex, int nFontHeight, LPCWSTR szText, DWORD dwFontFormat, const SUICoord &ScreenCoord, SFontDrawEffectInfo& Info)
{
int nFontIndex = GetFontIndex( nFontSetIndex, nFontHeight );
if( nFontIndex < 0 || nFontIndex >= (int)m_vecFont.size() )
return;
float fTempWidth = ScreenCoord.fWidth * GetEtDevice()->Width();
float fTempHeight = ScreenCoord.fHeight * GetEtDevice()->Height();
SUICoord ScreenCoordBackup = ScreenCoord;
SFontDrawEffectInfo NormalEffectInfo = Info;
NormalEffectInfo.nDrawType = SFontDrawEffectInfo::NORMAL;
NormalEffectInfo.fGlobalBlurAlphaWeight = 0.0f;
result = GetFontTexture(nFontIndex, szText, fTempWidth, dwFontFormat, NormalEffectInfo, true);
}
bool CEtFontMng::IsExistAddFontResourceList( SFontInfo& stFontInfo )
{
bool bExist = false;
for( int i=0; i<static_cast<int>( m_vecAddFontMemResourceList.size() ); i++ )
{
if( strcmp( m_vecAddFontMemResourceList[i].szFontName, stFontInfo.szFontName ) == 0 )
{
bExist = true;
break;
}
}
return bExist;
}
HFONT CEtFontMng::FindFontHandle( SFontInfo& stFontInfo )
{
HFONT hFont = NULL;
for( int i=0; i<static_cast<int>( m_vecStFontList.size() ); i++ )
{
if( m_vecStFontList[i].nFontHeight == stFontInfo.nFontHeight
&& strcmp( m_vecStFontList[i].szFontName, stFontInfo.szFontName ) == 0 )
{
hFont = m_vecStFontList[i].hFont;
break;
}
}
return hFont;
}
int CEtFontMng::GetGlyphGOffset( SFontInfo& stFontInfo, wstring& strText, vector<WORD>& vecGlyph, vector<GOFFSET>& vecGOffset )
{
HDC hDC = ::GetDC( GetEtDevice()->GetHWnd() );
if( hDC == NULL )
return 0;
HFONT hFont = FindFontHandle( stFontInfo );
if( hFont == NULL )
{
::ReleaseDC( GetEtDevice()->GetHWnd(), hDC );
return 0;
}
HFONT hOldFont = (HFONT)SelectObject( hDC, hFont );
HRESULT hResult;
int nStrLength = static_cast<int>( strText.length() );
if( nStrLength <= 0 )
return 0;
const SCRIPT_CONTROL *psControl = NULL;
const SCRIPT_STATE *psState = NULL;
int cMaxItems = nStrLength + 1;
SCRIPT_ITEM* psItems = new SCRIPT_ITEM[cMaxItems];
int nItemCount;
/* Itemize */
hResult = ScriptItemize( strText.c_str(), nStrLength, cMaxItems, psControl, psState, psItems, &nItemCount );
if( SUCCEEDED( hResult ) == FALSE )
{
SAFE_DELETE( psItems );
::ReleaseDC( GetEtDevice()->GetHWnd(), hDC );
return 0;
}
SCRIPT_CACHE sCache = NULL;
WORD* pwdClusts = NULL;
WORD* pwdGlyphs = NULL;
SCRIPT_VISATTR* psVisattr = NULL;
int* pnAdvance = NULL;
GOFFSET* pGOffset = NULL;
for( int i=0; i<nItemCount; i++ )
{
int nIndex = psItems[i].iCharPos;
int nChars = psItems[i+1].iCharPos - nIndex;
int nMaxGlyph = nChars * 2 + 16;
int nGlyphCount = 0;
pwdClusts = new WORD[nMaxGlyph];
pwdGlyphs = new WORD[nMaxGlyph];
psVisattr = new SCRIPT_VISATTR[nMaxGlyph];
/* Shape */
hResult = ScriptShape( hDC, &sCache, strText.c_str()+nIndex, nChars, nMaxGlyph, &psItems[i].a, pwdGlyphs, pwdClusts, psVisattr, &nGlyphCount );
if( SUCCEEDED( hResult ) == FALSE )
break;
ABC abc;
pGOffset = new GOFFSET[nMaxGlyph];
pnAdvance = new int[nMaxGlyph];
/* Place */
hResult = ScriptPlace( hDC, &sCache, pwdGlyphs, nGlyphCount, psVisattr, &psItems[i].a, pnAdvance, pGOffset, &abc );
if( SUCCEEDED( hResult ) == FALSE )
break;
for( int k=0; k<nGlyphCount; k++ )
{
vecGOffset.push_back( pGOffset[k] );
vecGlyph.push_back( pwdGlyphs[k] );
}
SAFE_DELETEA( pwdClusts );
SAFE_DELETEA( pwdGlyphs );
SAFE_DELETEA( psVisattr );
SAFE_DELETEA( pnAdvance );
SAFE_DELETEA( pGOffset );
}
SAFE_DELETEA( psItems );
SAFE_DELETEA( pwdClusts );
SAFE_DELETEA( pwdGlyphs );
SAFE_DELETEA( psVisattr );
SAFE_DELETEA( pnAdvance );
SAFE_DELETEA( pGOffset );
ScriptFreeCache(&sCache);
SelectObject( hDC, hOldFont );
::ReleaseDC( GetEtDevice()->GetHWnd(), hDC );
return static_cast<int>( vecGOffset.size() );
}
typedef struct _tagTT_OFFSET_TABLE
{
USHORT uMajorVersion;
USHORT uMinorVersion;
USHORT uNumOfTables;
USHORT uSearchRange;
USHORT uEntrySelector;
USHORT uRangeShift;
}TT_OFFSET_TABLE;
typedef struct _tagTT_TABLE_DIRECTORY
{
char szTag[4]; //table name
ULONG uCheckSum; //Check sum
ULONG uOffset; //Offset from beginning of file
ULONG uLength; //length of the table in bytes
}TT_TABLE_DIRECTORY;
typedef struct _tagTT_NAME_TABLE_HEADER
{
USHORT uFSelector; //format selector. Always 0
USHORT uNRCount; //Name Records count
USHORT uStorageOffset; //Offset for strings storage, from start of the table
}TT_NAME_TABLE_HEADER;
typedef struct _tagTT_NAME_RECORD
{
USHORT uPlatformID;
USHORT uEncodingID;
USHORT uLanguageID;
USHORT uNameID;
USHORT uStringLength;
USHORT uStringOffset; //from start of storage area
}TT_NAME_RECORD;
#define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
#define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))
void CEtFontMng::GetTTFLocalFontName( const char* pFontFileName, char* pChangeFontName )
{
if( pFontFileName == NULL || pChangeFontName == NULL )
return;
CResMngStream Stream;
Stream.Open( pFontFileName );
if( !Stream.IsValid() )
{
Stream.Close();
return;
}
TT_OFFSET_TABLE ttOffsetTable;
Stream.Read( &ttOffsetTable, sizeof( TT_OFFSET_TABLE ) );
ttOffsetTable.uNumOfTables = SWAPWORD( ttOffsetTable.uNumOfTables );
ttOffsetTable.uMajorVersion = SWAPWORD( ttOffsetTable.uMajorVersion );
ttOffsetTable.uMinorVersion = SWAPWORD( ttOffsetTable.uMinorVersion );
//check is this is a true type font and the version is 1.0
// if( ttOffsetTable.uMajorVersion != 1 || ttOffsetTable.uMinorVersion != 0 )
// {
// Stream.Close();
// return;
// }
TT_TABLE_DIRECTORY tblDir;
BOOL bFound = FALSE;
CString csTemp;
for( int i=0; i<ttOffsetTable.uNumOfTables; i++ )
{
Stream.Read( &tblDir, sizeof( TT_TABLE_DIRECTORY ) );
strncpy( csTemp.GetBuffer(5), tblDir.szTag, 4 );
csTemp.ReleaseBuffer( 4 );
if( csTemp.CompareNoCase( _T( "name" ) ) == 0 )
{
bFound = TRUE;
tblDir.uLength = SWAPLONG( tblDir.uLength );
tblDir.uOffset = SWAPLONG( tblDir.uOffset );
break;
}
}
if( bFound )
{
Stream.Seek( tblDir.uOffset, SEEK_SET );
TT_NAME_TABLE_HEADER ttNTHeader;
Stream.Read( &ttNTHeader, sizeof( TT_NAME_TABLE_HEADER ) );
ttNTHeader.uNRCount = SWAPWORD( ttNTHeader.uNRCount );
ttNTHeader.uStorageOffset = SWAPWORD( ttNTHeader.uStorageOffset );
TT_NAME_RECORD ttRecord;
bFound = FALSE;
for( int i=0; i<ttNTHeader.uNRCount; i++ )
{
Stream.Read( &ttRecord, sizeof( TT_NAME_RECORD ) );
ttRecord.uNameID = SWAPWORD( ttRecord.uNameID );
if( ttRecord.uNameID == 4 )
{
ttRecord.uStringLength = SWAPWORD( ttRecord.uStringLength );
ttRecord.uStringOffset = SWAPWORD( ttRecord.uStringOffset );
int nPos = Stream.SeekCur<int>();
Stream.Seek( tblDir.uOffset + ttRecord.uStringOffset + ttNTHeader.uStorageOffset, SEEK_SET );
char* pCharFontName = new char[ ttRecord.uStringLength + 1 ];
ZeroMemory( pCharFontName, ttRecord.uStringLength + 1 );
Stream.Read( pCharFontName, ttRecord.uStringLength );
if( strlen( pCharFontName ) > 0 )
{
strcpy_s( pChangeFontName, LF_FACESIZE, pCharFontName );
}
else if( pCharFontName[0] == '\0' ) // UTf8 encoding font name
{
int nCount = 0;
for( int j=1; j<ttRecord.uStringLength; j+=2 )
{
pChangeFontName[ nCount++ ] = pCharFontName[j];
}
}
SAFE_DELETEA( pCharFontName );
if( strlen( pChangeFontName ) > 0 )
break;
Stream.Seek( nPos, SEEK_SET );
}
}
}
Stream.Close();
}
int CEtFontMng::GetCaretPos( LPCWSTR szText, int& nFontSetIndex, int nFontHeight, int nCharIndex, int* pHeight/* = NULL*/, bool bUseCache )
{
ScopeLock<CSyncLock> Lock(s_Lock);
if( nCharIndex <= 0 )
{
ASSERT( nCharIndex <= 0 );
return 0;
}
nCharIndex -= 1;
int nLen = (int)wcslen( szText );
ASSERT( m_vecFont.size() && "CEtFontMng::GetCaretPos" );
if( m_vecFont.empty() ) {
return -1;
}
ASSERT( nFontHeight >=0 && "CEtFontMng::GetCaretPos" );
if( nLen == 0 ) {
return -1;
}
ASSERT( nCharIndex < nLen && "CEtFontMng::DrawTextW" );
int nSentenceWidth = 0;
int nFontIndex = GetFontIndex( nFontSetIndex, nFontHeight );
bool bBold = (m_vecFont[ nFontIndex ].nFontWeight*100 >= FW_BOLD);
FT_Face Face = m_vecFont[ nFontIndex ].Face;
// ij<><C4B3><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20>Ÿ<EFBFBD> <20≯<EFBFBD> <20><><EFBFBD>س<EFBFBD><D8B3><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (bUseCache)
{
SCaretKey caretKey;
caretKey.szText = szText;
caretKey.nFontIndex = nFontIndex;
if( m_caretInfo.count( caretKey ) != 0 )
{
const SCaretInfo &caretInfo = m_caretInfo[ caretKey ];
ASSERT( wcscmp(caretKey.szText.c_str(), szText) == 0 );
// <20><><EFBFBD>࿡ nCharIndex <20><> 1<><31> <20><> ũ<>ٸ<EFBFBD> <20>׳<EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD> <20>ȴ<EFBFBD>.
// <20>߰<EFBFBD><DFB0><EFBFBD> \n <20><> <20><> <20><><EFBFBD>ڿ<EFBFBD><DABF><EFBFBD> <20><><EFBFBD><EFBFBD> <20>׷<EFBFBD><D7B7><EFBFBD> <20>ȴ<EFBFBD>.
if( nCharIndex < (int)caretInfo.vecCaretPos.size() )
nSentenceWidth = caretInfo.vecCaretPos.at( nCharIndex );
else
nSentenceWidth = caretInfo.vecCaretPos.back();
if( pHeight )
*pHeight = caretInfo.nHeight;
return nSentenceWidth;
}
}
SFontInfo& FontInfo = m_vecFont[ nFontIndex ];
for ( int i = 0; i <= nCharIndex; ++i )
{
FT_ULong ch = szText[ i ];
int nAdvanceX = GetCachedCharAdvanceX( Face, FontInfo, (wchar_t)ch, bBold, nSentenceWidth );
if( nAdvanceX < 0 )
continue;
// <20><><EFBFBD><EFBFBD> <20><> <20><> <20>ʺ<EFBFBD> <20><><EFBFBD><EFBFBD>
nSentenceWidth += nAdvanceX;
}
// NOTE: <20><><EFBFBD>̰<EFBFBD><CCB0><EFBFBD> <20>׳<EFBFBD> <20≯<EFBFBD> <20>Ѱܹ<D1B0><DCB9><EFBFBD><EFBFBD><EFBFBD> \n <20><> <20><><EFBFBD><20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
// CalcRect <20><><EFBFBD><EFBFBD> rect <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ȵ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ִ<EFBFBD>..
// <20><><EFBFBD>ʺ<EFBFBD><CABA><EFBFBD> CalcRect <20><><EFBFBD><EFBFBD> <20><> <20>Լ<EFBFBD> ȣ<><C8A3><EFBFBD>ϴ°<CFB4> <20>߸<EFBFBD><DFB8><EFBFBD> <20>ű<EFBFBD> <20>ѵ<EFBFBD>..
if( pHeight )
*pHeight = Face->size->metrics.y_ppem;
return nSentenceWidth;
}
int CEtFontMng::GetCaretFromCaretPos( LPCWSTR szText, int& nFontSetIndex, int nFontHeight, int nCaretPos, int& nTrail )
{
ScopeLock<CSyncLock> Lock(s_Lock);
int nLen = (int)wcslen( szText );
ASSERT( m_vecFont.size() && "CEtFontMng::GetCaretPos" );
ASSERT( nFontHeight >=0 && "CEtFontMng::GetCaretPos" );
if( nLen == 0 ) {
return -1;
}
nTrail = 0;
int nCaretIndex = 0;
int nFontIndex = GetFontIndex( nFontSetIndex, nFontHeight );
bool bBold = (m_vecFont[ nFontIndex ].nFontWeight*100 >= FW_BOLD);
// ij<><C4B3><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20>Ÿ<EFBFBD> <20≯<EFBFBD> <20><><EFBFBD>س<EFBFBD><D8B3><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
SCaretKey caretKey;
caretKey.szText = szText;
caretKey.nFontIndex = nFontIndex;
if( m_caretInfo.count( caretKey ) != 0 )
{
const SCaretInfo &caretInfo = m_caretInfo[ caretKey ];
ASSERT( wcscmp(caretKey.szText.c_str(), szText) == 0 );
map<int, int>::const_iterator iter = caretInfo.mapPosByCaret.find( nCaretPos );
if( caretInfo.mapPosByCaret.end() != iter )
{
nCaretIndex = iter->second;
return nCaretIndex;
}
else
{
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD>..
int nApproximateCaretIndex = (int)caretInfo.vecCaretPos.size()-1;
nTrail = 1;
int nNumCaret = (int)caretInfo.vecCaretPos.size();
for( int nCaret = 0; nCaret < nNumCaret; ++nCaret )
{
int nNowCaretPos = caretInfo.vecCaretPos.at( nCaret );
if( nNowCaretPos > nCaretPos )
{
nApproximateCaretIndex = nCaret;
nTrail = 0;
break;
}
}
return nApproximateCaretIndex;
}
}
SFontInfo& FontInfo = m_vecFont[ nFontIndex ];
int nSentenceWidth = 0;
FT_Face Face = m_vecFont[ nFontIndex ].Face;
for ( int i = 0; i < nLen; ++i )
{
int nAdvanceX = GetCachedCharAdvanceX( Face, FontInfo, szText[i], bBold, nSentenceWidth );
if( nAdvanceX < 0 )
continue;
// <20><><EFBFBD><EFBFBD> <20><> <20><> <20>ʺ<EFBFBD> <20><><EFBFBD><EFBFBD>
nSentenceWidth += nAdvanceX;
if( nCaretPos < nSentenceWidth )
{
nCaretIndex = i;
return nCaretIndex;
}
}
// <20><> ã<><C3A3><EFBFBD><EFBFBD> <20>׳<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
nTrail = 1;
nCaretIndex = nLen - 1;
return nCaretIndex;
}
void CEtFontMng::DrawTextW( int &nFontSetIndex, int nFontHeight, LPCWSTR szText, DWORD dwFontFormat, SUICoord &ScreenCoord, int nCount,
SFontDrawEffectInfo& FontEffectInfo, bool bRemoveCache /*= true */, float ZValue/* = 0.f*/, DWORD dwBgColor/* = 0*/, int nBorderFlag/* = 0*/)
{
ScopeLock<CSyncLock> Lock(s_Lock);
ASSERT(m_vecFont.size()&&"CEtFontMng::DrawTextW");
ASSERT(nFontSetIndex>=0&&"CEtFontMng::DrawTextW");
int nLen = (int)wcslen( szText );
if( nLen == 0 ) {
return;
}
int nFontIndex = GetFontIndex( nFontSetIndex, nFontHeight );
if( nFontIndex < 0 || nFontIndex >= (int)m_vecFont.size() ) return;
float fWidth = ScreenCoord.fWidth * GetEtDevice()->Width();
float fHeight = ScreenCoord.fHeight * GetEtDevice()->Height();
SUICoord ScreenCoordBackup = ScreenCoord;
// Global Blur <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵٸ<D1B4> <20>ٸ<EFBFBD> <20><>Ʈȿ<C6AE><C8BF><EFBFBD>ʹ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><> <20><> <20>׷<EFBFBD><D7B7>ش<EFBFBD>.
SFontDrawEffectInfo NormalEffectInfo = FontEffectInfo;
NormalEffectInfo.nDrawType = SFontDrawEffectInfo::NORMAL;
NormalEffectInfo.fGlobalBlurAlphaWeight = 0.0f;
SFontTextureInfo TextureInfo = GetFontTexture( nFontIndex, szText, fWidth, dwFontFormat, NormalEffectInfo, bRemoveCache );
float fShear = m_vecFont[ nFontIndex ].bItalic ? 0.3f : 0.0f;
float fHalfSizeX = ((fWidth-TextureInfo.Width)*0.5f) / GetEtDevice()->Width();
float fHalfSizeY = ((fHeight-TextureInfo.Height)*0.5f) / GetEtDevice()->Height();
ScreenCoord.fX += fHalfSizeX;
ScreenCoord.fY += fHalfSizeY;
if( dwFontFormat & DT_RIGHT ) {
ScreenCoord.fX += fHalfSizeX;
}
else if ( !(dwFontFormat & DT_CENTER) ){
ScreenCoord.fX -= fHalfSizeX;
}
if( dwFontFormat & DT_BOTTOM ) {
ScreenCoord.fY += fHalfSizeY;
}
else if ( !(dwFontFormat & DT_VCENTER) ){
ScreenCoord.fY -= fHalfSizeY;
}
float fFracX = ScreenCoord.fX * GetEtDevice()->Width();
float fFracY = ScreenCoord.fY * GetEtDevice()->Height();
fFracX -= (int)fFracX;
fFracY -= (int)fFracY;
ScreenCoord.fX -= fFracX / GetEtDevice()->Width();
ScreenCoord.fY -= fFracY / GetEtDevice()->Height();
EtTextureHandle hFontTexture = TextureInfo.hTexture;
if( !hFontTexture ) return;
ScreenCoord.fWidth = (float)hFontTexture->Width() / GetEtDevice()->Width();
ScreenCoord.fHeight = (float)hFontTexture->Height() / GetEtDevice()->Height();
SUICoord UVCoord;
UVCoord.SetCoord( 0.0f, 0.0f, 1.0f, 1.0f );
#if defined( PRE_MOD_MINIMIZE_FORCE_BLUR )
if( true == m_bForceBlur && m_vecFont[ nFontIndex ].nFontHeight < m_nMinimizeSize && FontEffectInfo.fGlobalBlurAlphaWeight < m_fBlurWeight )
FontEffectInfo.fGlobalBlurAlphaWeight = m_fBlurWeight;
#endif // #if defined( PRE_MOD_MINIMIZE_FORCE_BLUR )
const bool bBegin = CEtSprite::GetInstance().IsBegin();
if( !bBegin )
CEtSprite::GetInstance().Begin( 0 );
if( dwBgColor != 0 )
{
SUICoord RectCoord;
RectCoord.fX = ScreenCoord.fX - ( (((nBorderFlag&1)>0)?4.f:0.f) / GetEtDevice()->Width());
RectCoord.fY = ScreenCoord.fY - ( (((nBorderFlag&4)>0)?2.f:0.f) / GetEtDevice()->Height());
int nAddWidth = ((nBorderFlag&1)>0)?4:0; nAddWidth += ((nBorderFlag&2)>0)?4:0;
int nAddHeight = ((nBorderFlag&4)>0)?2:0; nAddHeight += ((nBorderFlag&8)>0)?3:0;
RectCoord.fWidth = (float)(TextureInfo.Width + nAddWidth) / GetEtDevice()->Width();
RectCoord.fHeight= (float)(TextureInfo.Height + nAddHeight) / GetEtDevice()->Height();
CEtSprite::GetInstance().DrawRect( RectCoord, dwBgColor, ZValue );
}
if( SFontDrawEffectInfo::NORMAL != FontEffectInfo.nDrawType )
{
SFontTextureInfo FontEffectTexture = GetFontTexture( nFontIndex, szText, fWidth, dwFontFormat, FontEffectInfo, bRemoveCache );
SUICoord EffectFontCoord = ScreenCoord;
if( s_bUseUniscribe )
{
EffectFontCoord.fX = ScreenCoord.fX - ((float)FontEffectInfo.nWeight / (float)GetEtDevice()->Width() );
EffectFontCoord.fY = ScreenCoord.fY - (( (float)FontEffectInfo.nWeight + UPPER_PADDING_PIXEL ) / (float)GetEtDevice()->Height() );
}
else
{
EffectFontCoord.fX = ScreenCoord.fX - ((float)FontEffectInfo.nWeight / (float)GetEtDevice()->Width() );
EffectFontCoord.fY = ScreenCoord.fY - ((float)FontEffectInfo.nWeight / (float)GetEtDevice()->Height() );
}
if( FontEffectTexture.hTexture )
{
EffectFontCoord.fWidth = (float)FontEffectTexture.hTexture->Width() / GetEtDevice()->Width();
EffectFontCoord.fHeight = (float)FontEffectTexture.hTexture->Height() / GetEtDevice()->Height();
CEtSprite::GetInstance().DrawSprite( (EtTexture*)FontEffectTexture.hTexture->GetTexturePtr(),
FontEffectTexture.hTexture->Width(), FontEffectTexture.hTexture->Height(),
UVCoord, FontEffectInfo.dwEffectColor, EffectFontCoord, 0.f, ZValue, fShear );
}
}
if( 0.0f != FontEffectInfo.fGlobalBlurAlphaWeight )
{
SFontDrawEffectInfo GlobalBlurEffectInfo = FontEffectInfo;
GlobalBlurEffectInfo.nDrawType = SFontDrawEffectInfo::GLOW;
GlobalBlurEffectInfo.nWeight = 1;
GlobalBlurEffectInfo.fAlphaWeight = GlobalBlurEffectInfo.fGlobalBlurAlphaWeight;
SFontTextureInfo GlobalBlurTextureInfo = GetFontTexture( nFontIndex, szText, fWidth, dwFontFormat, GlobalBlurEffectInfo, bRemoveCache );
SUICoord EffectFontCoord = ScreenCoord;
if( s_bUseUniscribe )
{
EffectFontCoord.fX = ScreenCoord.fX - ((float)GlobalBlurEffectInfo.nWeight / (float)GetEtDevice()->Width() );
EffectFontCoord.fY = ScreenCoord.fY - (( (float)GlobalBlurEffectInfo.nWeight + UPPER_PADDING_PIXEL ) / (float)GetEtDevice()->Height() );
}
else
{
EffectFontCoord.fX = ScreenCoord.fX - ((float)GlobalBlurEffectInfo.nWeight / (float)GetEtDevice()->Width() );
EffectFontCoord.fY = ScreenCoord.fY - ((float)GlobalBlurEffectInfo.nWeight / (float)GetEtDevice()->Height() );
}
EffectFontCoord.fWidth = (float)GlobalBlurTextureInfo.hTexture->Width() / GetEtDevice()->Width();
EffectFontCoord.fHeight = (float)GlobalBlurTextureInfo.hTexture->Height() / GetEtDevice()->Height();
CEtSprite::GetInstance().DrawSprite( (EtTexture*)GlobalBlurTextureInfo.hTexture->GetTexturePtr(),
GlobalBlurTextureInfo.hTexture->Width(), GlobalBlurTextureInfo.hTexture->Height(),
UVCoord, GlobalBlurEffectInfo.dwFontColor, EffectFontCoord, 0.f, ZValue, fShear );
}
if( hFontTexture )
{
if( s_bUseUniscribe )
{
SUICoord FontCoord = ScreenCoord;
FontCoord.fY = ScreenCoord.fY - ( UPPER_PADDING_PIXEL / (float)GetEtDevice()->Height() );
CEtSprite::GetInstance().DrawSprite( (EtTexture*)hFontTexture->GetTexturePtr(), hFontTexture->Width(), hFontTexture->Height(),
UVCoord, FontEffectInfo.dwFontColor, FontCoord, 0.f, ZValue, fShear );
}
else
{
CEtSprite::GetInstance().DrawSprite( (EtTexture*)hFontTexture->GetTexturePtr(), hFontTexture->Width(), hFontTexture->Height(),
UVCoord, FontEffectInfo.dwFontColor, ScreenCoord, 0.f, ZValue, fShear );
}
}
if( !bBegin )
CEtSprite::GetInstance().End();
ScreenCoord = ScreenCoordBackup;
}
void CEtFontMng::DrawTextW3D( int &nFontSetIndex, int nFontHeight, LPCWSTR szText, EtVector3 &vPosition, SFontDrawEffectInfo& FontEffectInfo,
int nCount, float fScale /*= 1.0f */ )
{
ScopeLock<CSyncLock> Lock(s_Lock);
if( g_bSkipScene )
{
return;
}
if( !CEtCamera::GetActiveCamera() )
{
return;
}
if( wcslen(szText) == 0 )
{
return;
}
ASSERT(m_vecFont.size()&&"CEtFontMng::DrawTextW3D");
ASSERT(nFontSetIndex>=0&&"CEtFontMng::DrawTextW3D");
int nFontIndex = GetFontIndex( nFontSetIndex, nFontHeight );
if( nFontIndex < 0 || nFontIndex >= (int)m_vecFont.size() ) return;
EtMatrix IdentMat, TextMat;
EtVector3 FontPos;
EtVec3TransformCoord( &FontPos, &vPosition, CEtCamera::GetActiveCamera()->GetViewMat() );
EtMatrixIdentity( &IdentMat );
GetEtDevice()->SetWorldTransform( &IdentMat );
GetEtDevice()->SetViewTransform( &IdentMat );
GetEtDevice()->SetProjTransform( CEtCamera::GetActiveCamera()->GetProjMat() );
ASSERT( !CEtSprite::GetInstance().IsBegin() );
CEtSprite::GetInstance().Begin( D3DXSPRITE_OBJECTSPACE );
EtMatrixRotationX( &TextMat, EtToRadian( 180.0f ) );
TextMat._41 = FontPos.x;
TextMat._42 = FontPos.y;
TextMat._43 = FontPos.z;
if( fScale != 1.0f )
{
EtMatrix ScaleMat;
EtMatrixScaling( &ScaleMat, fScale, fScale, fScale );
EtMatrixMultiply( &TextMat, &ScaleMat, &TextMat );
}
CEtSprite::GetInstance().SetTransform( TextMat );
// BLUR Ÿ<><C5B8><EFBFBD>̶<EFBFBD><CCB6><EFBFBD> <20><>Ʈ <20>ؽ<EFBFBD><D8BD>ĸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʴ´<CAB4>.
if( SFontDrawEffectInfo::NORMAL != FontEffectInfo.nDrawType )
{
SFontTextureInfo FontEffectTexture = GetFontTexture( nFontIndex, szText, 1024.0f, 0, FontEffectInfo );
//SUICoord EffectFontCoord = ScreenCoord;
//EffectFontCoord.fX = ScreenCoord.fX - ((float)FontEffectInfo.nWeight / (float)GetEtDevice()->Width() );
//EffectFontCoord.fY = ScreenCoord.fY - ((float)FontEffectInfo.nWeight / (float)GetEtDevice()->Height() );
//EffectFontCoord.fWidth = (float)FontEffectTexture.hTexture->Width() / GetEtDevice()->Width();
//EffectFontCoord.fHeight = (float)FontEffectTexture.hTexture->Height() / GetEtDevice()->Height();
RECT Rect;
SetRect( &Rect, FontEffectInfo.nWeight, FontEffectInfo.nWeight, FontEffectTexture.hTexture->Width(), FontEffectTexture.hTexture->Height() );
//((LPDIRECT3DDEVICE9)CEtDevice::GetInstance().GetDevicePtr())->SetRenderState( D3DRS_ZENABLE, FALSE );
CEtSprite::GetInstance().Draw( (EtTexture*)FontEffectTexture.hTexture->GetTexturePtr(), &Rect, NULL, NULL,
FontEffectInfo.dwEffectColor );
//((LPDIRECT3DDEVICE9)CEtDevice::GetInstance().GetDevicePtr())->SetRenderState( D3DRS_ZENABLE, TRUE );
//CEtSprite::GetInstance().DrawSprite( (EtTexture*)FontEffectTexture.hTexture->GetTexturePtr(),
// FontEffectTexture.hTexture->Width(), FontEffectTexture.hTexture->Height(),
// UVCoord, FontEffectInfo.dwEffectColor, EffectFontCoord, 0.0f );
}
// BLUR Ÿ<><C5B8><EFBFBD>̶<EFBFBD><CCB6><EFBFBD> <20><>Ʈ <20>ؽ<EFBFBD><D8BD>ĸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʴ´<CAB4>.
SFontDrawEffectInfo NormalEffectInfo = FontEffectInfo;
NormalEffectInfo.nDrawType = SFontDrawEffectInfo::NORMAL;
SFontTextureInfo TextureInfo = GetFontTexture( nFontIndex, szText, 1024.f, 0, NormalEffectInfo );
EtTextureHandle hFontTexture = TextureInfo.hTexture;
if( hFontTexture )
{
RECT Rect;
SetRect( &Rect, 0, 0, hFontTexture->Width(), hFontTexture->Height());
//for( int i = 0; i < 3; ++i )
/*LPDIRECT3DDEVICE9 pd3dDevice = ((LPDIRECT3DDEVICE9)CEtDevice::GetInstance().GetDevicePtr());*/
//GetEtDevice()->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
CEtSprite::GetInstance().Draw( (EtTexture*)hFontTexture->GetTexturePtr(), &Rect, NULL, NULL, FontEffectInfo.dwFontColor );
//GetEtDevice()->SetSamplerState( D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
}
CEtSprite::GetInstance().End();
}
void CEtFontMng::CalcTextRect( int &nFontSetIndex, int nFontHeight, LPCWSTR szText, DWORD dwFontFormat, SUICoord &CalcCoord, int nCount, bool bUseCache )
{
ScopeLock<CSyncLock> Lock(s_Lock);
ASSERT(m_vecFont.size()&&"CEtFontMng::CalcTextRect");
ASSERT(nFontSetIndex>=0&&"CEtFontMng::CalcTextRect");
int nHeight = 0;
int nWidth = GetCaretPos( szText, nFontSetIndex, nFontHeight, (int)wcslen(szText), &nHeight, bUseCache );
CalcCoord.fWidth = ( nWidth ) / ( float )GetEtDevice()->Width();
CalcCoord.fHeight = ( nHeight) / ( float )GetEtDevice()->Height();
}
void CEtFontMng::OnLostDevice()
{
ScopeLock<CSyncLock> Lock(s_Lock);
m_mapFontIndex.clear();
DeleteAllFont();
}
void CEtFontMng::OnResetDevice()
{
ScopeLock<CSyncLock> Lock(s_Lock);
int i, nFontIndex(-1);
for( i=0; i<(int)m_vecFontSet.size(); i++ )
{
nFontIndex = AddFont( m_vecFontSet[i].strFullFileName.c_str(), m_vecFontSet[i].strFontName.c_str(), m_vecFontSet[i].nFontHeight, m_vecFontSet[i].nFontWeight, m_vecFontSet[i].bItalic );
m_mapFontIndex.insert( std::make_pair( m_vecFontSet[i].nIndex, nFontIndex ) );
}
int nSize;
nSize = (int)m_cachedFontList.size();
for( i = 0; i < nSize; i++) {
SAFE_RELEASE_SPTR( m_cachedFontList[i].TextureInfo.hTexture );
}
m_cachedFontList.clear();
std::list< EtTextureHandle >::iterator it = m_texturePool.begin();
for( std::list< EtTextureHandle >::iterator it = m_texturePool.begin(); it != m_texturePool.end(); it++ ) {
SAFE_RELEASE_SPTR( (*it) );
}
m_texturePool.clear();
m_caretInfo.clear();
}
void CEtFontMng::AddFontSet( SUIFontSet &fontSet )
{
m_vecFontSet.push_back( fontSet );
int nFontIndex = AddFont( fontSet.strFileName.c_str(), fontSet.strFontName.c_str(), fontSet.nFontHeight, fontSet.nFontWeight, fontSet.bItalic );
m_mapFontIndex.insert( std::make_pair( fontSet.nIndex, nFontIndex ) );
}
void CEtFontMng::DeleteFontSet( int nIndex )
{
if( m_vecFontSet.empty() ) return;
if( nIndex < 0 ) return;
if( nIndex >= (int)m_vecFontSet.size() ) return;
std::map<int,int>::iterator iter;
iter = m_mapFontIndex.find( m_vecFontSet[nIndex].nIndex );
if( iter != m_mapFontIndex.end() )
{
m_mapFontIndex.erase(iter);
}
m_vecFontSet.erase( m_vecFontSet.begin()+nIndex );
}
void CEtFontMng::ModifyFontSet( int nIndex, SUIFontSet &fontSet )
{
if( m_vecFontSet.empty() ) return;
if( nIndex < 0 ) return;
if( nIndex >= (int)m_vecFontSet.size() ) return;
m_vecFontSet[nIndex] = fontSet;
int nFontIndex = AddFont( fontSet.strFileName.c_str(), fontSet.strFontName.c_str(), fontSet.nFontHeight, fontSet.nFontWeight, fontSet.bItalic );
m_mapFontIndex[m_vecFontSet[nIndex].nIndex] = nFontIndex;
}
SUIFontSet *CEtFontMng::GetFontSet( int nIndex )
{
if( m_vecFontSet.empty() ) return NULL;
if( nIndex < 0 ) return NULL;
if( nIndex >= (int)m_vecFontSet.size() ) return NULL;
return &m_vecFontSet[nIndex];
}
bool CEtFontMng::LoadFontSet( const char *szFileName )
{
Finalize();
CResMngStream Stream( szFileName );
if( Stream.IsValid() )
{
m_strFontSetFileName = szFileName;
m_vecFontSet.clear();
int nCount;
Stream >> nCount;
if( nCount <= 0 )
return false;
m_vecFontSet.resize(nCount);
for( int i=0; i<(int)m_vecFontSet.size(); i++ )
{
m_vecFontSet[i].Load( Stream );
}
std::string strFileName;
std::string::size_type offSet;
offSet = m_strFontSetFileName.find_last_of( "\\" );
if( offSet != std::string::npos )
{
strFileName = m_strFontSetFileName.substr( 0, offSet+1 );
}
int nFontIndex(-1);
for( int i=0; i<(int)m_vecFontSet.size(); i++ )
{
std::string strTemp = strFileName + m_vecFontSet[i].strFileName;
m_vecFontSet[i].strFullFileName = strFileName + m_vecFontSet[i].strFileName; // FreeType <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߰<EFBFBD>
nFontIndex = AddFont( strTemp.c_str(), m_vecFontSet[i].strFontName.c_str(), m_vecFontSet[i].nFontHeight, m_vecFontSet[i].nFontWeight, m_vecFontSet[i].bItalic );
m_mapFontIndex.insert( std::make_pair( m_vecFontSet[i].nIndex, nFontIndex ) );
}
return true;
}
return false;
}
void CEtFontMng::SaveFontSet( const char *szFileName )
{
CFileStream Stream( szFileName, CFileStream::OPEN_WRITE );
if( Stream.IsValid() )
{
Stream << (int)m_vecFontSet.size();
for( int i=0; i<(int)m_vecFontSet.size(); i++ )
{
m_vecFontSet[i].Save( Stream );
}
}
}
int CEtFontMng::GetFontIndex( int &nFontSetIndex, int nFontHeight )
{
std::map<int,int>::iterator iter;
iter = m_mapFontIndex.find( nFontSetIndex );
if( iter != m_mapFontIndex.end() )
{
return iter->second;
}
else
{
int nRetIndex(0), nFontIndex(0);
int nTemp, nValue(INT_MAX);
// Note : ũ<><20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> ã<>´<EFBFBD>.
//
for( iter=m_mapFontIndex.begin(); iter != m_mapFontIndex.end(); ++iter )
{
nTemp = abs(m_vecFont[iter->second].nFontHeight - nFontHeight);
if( nValue > nTemp )
{
nValue = nTemp;
nFontIndex = iter->first;
nRetIndex = iter->second;
}
}
//CDebugSet::ToLogFile( "CEtFontMng::GetFontIndex, FontSetIndex:%d->%d, FontIndex:%d", nFontSetIndex, nFontIndex, nRetIndex );
nFontSetIndex = nFontIndex;
return nRetIndex;
}
}
int CEtFontMng::GetFontSetIndex()
{
std::map<int,int>::iterator iter;
for( int i=0; true; i++ )
{
iter = m_mapFontIndex.find( i );
if( iter == m_mapFontIndex.end() )
{
return i;
}
}
}
// Use Uniscribe Function.
bool CEtFontMng::IsSymbol( wchar_t cText )
{
bool bIsSymbol = false;
if( cText == L'.' ||
cText == L',' ||
cText == L'*' ||
cText == L'%' ||
cText == L'/' ||
cText == L'(' ||
cText == L')' ||
cText == L'[' ||
cText == L']' ||
cText == L'<' ||
cText == L'>' ||
cText == L':' ||
cText == L'!' ||
cText == L'?' ||
cText == L'\"' ||
cText == L'\'' ) // I'll <20>Ǵ<EFBFBD> target's
{
bIsSymbol = true;
}
return bIsSymbol;
}
bool CEtFontMng::IsOpenBraket( wchar_t cText )
{
bool bIsOpenBraket = false;
if( cText == L'(' ||
cText == L'[' ||
cText == L'<' )
{
bIsOpenBraket = true;
}
return bIsOpenBraket;
}
void CEtFontMng::GetWordBreakInfo( wstring& strText, vector<SCRIPT_LOGATTR>& vecLogAttr )
{
HRESULT hResult;
int nStrLength = static_cast<int>( strText.length() );
if( nStrLength <= 0 )
return;
const SCRIPT_CONTROL *psControl = NULL;
const SCRIPT_STATE *psState = NULL;
int cMaxItems = nStrLength + 1;
SCRIPT_ITEM* psItems = new SCRIPT_ITEM[cMaxItems];
int nItemCount;
hResult = ScriptItemize( strText.c_str(), nStrLength, cMaxItems, psControl, psState, psItems, &nItemCount );
if( SUCCEEDED( hResult ) == FALSE )
{
SAFE_DELETEA( psItems );
return;
}
SCRIPT_LOGATTR* psLogAttr = NULL;
bool bIsPrevSymbol = false;
for( int i=0; i<nItemCount; i++ )
{
int nIndex = psItems[i].iCharPos;
int nChars = psItems[i+1].iCharPos - nIndex;
psLogAttr = new SCRIPT_LOGATTR[nChars];
ScriptBreak( strText.c_str()+nIndex, nChars, &psItems[i].a, psLogAttr );
for( int k=0; k<nChars; k++ )
{
if( i > 0 && k == 0 )
psLogAttr[k].fSoftBreak = 1;
if( nChars == 1 )
{
if( IsSymbol( strText.at( nIndex ) ) )
{
psLogAttr[k].fSoftBreak = 0;
bIsPrevSymbol = true;
vecLogAttr.push_back( psLogAttr[k] );
continue;
}
else if( strText.at( nIndex ) == L'-' )
{
if( nIndex > 0 && nIndex + 1 < static_cast<int>( strText.length() ) &&
strText.at( nIndex - 1 ) != L' ' && strText.at( nIndex + 1 ) != L' ' )
psLogAttr[k].fSoftBreak = 0;
}
}
if( bIsPrevSymbol )
{
if( psLogAttr[k].fSoftBreak == 1 && nIndex > 0 )
{
if( IsSymbol( strText.at( nIndex - 1 ) ) )
{
psLogAttr[k].fSoftBreak = 0;
}
}
bIsPrevSymbol = false;
}
if( IsSymbol( strText.at( nIndex ) ) )
{
psLogAttr[k].fSoftBreak = 0;
}
vecLogAttr.push_back( psLogAttr[k] );
}
SAFE_DELETEA( psLogAttr );
}
SAFE_DELETEA( psItems );
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><> <20>ܾ<EFBFBD><DCBE><EFBFBD> softbreak <20>־<EFBFBD><D6BE><EFBFBD>
for( int i=0; i<static_cast<int>( vecLogAttr.size() ); i++ )
{
if( strText.at(i) != ' ' )
{
vecLogAttr[i].fSoftBreak = 1;
break;
}
}
// <20><>ȣ<EFBFBD><C8A3> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><20><><EFBFBD>ؼ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ȣ<EFBFBD><C8A3> softbreak <20>־<EFBFBD><D6BE><EFBFBD>
if( vecLogAttr.size() == strText.length() )
{
for( int i=0; i<strText.length(); i++ )
{
if( IsOpenBraket( strText.at( i ) ) )
{
vecLogAttr[i].fSoftBreak = 1;
if( i+1 < static_cast<int>( vecLogAttr.size() ) && vecLogAttr[i+1].fSoftBreak == 1 )
{
vecLogAttr[i+1].fSoftBreak = 0;
}
}
}
}
}
bool CEtFontMng::GetWordBreakText( wstring& strText, int nFontSetIndex, int nFontHeight, float fWidth,
vector<wstring>& vecStrLine, int& nMaxWidth, bool bUseRemainWidth, float fOriginWidth )
{
int nFontIndex = GetFontIndex( nFontSetIndex, nFontHeight );
if( !GetEtDevice() || strText.length() == 0 || fWidth <= 0.0f )
return false;
if( nFontIndex < 0 || nFontIndex >= static_cast<int>( m_vecFont.size() ) )
return false;
if( bUseRemainWidth )
m_fOriginWidth = fOriginWidth;
SCaretKey CaretKey;
CaretKey.szText = strText;
CaretKey.nFontIndex = nFontIndex;
FT_Face Face = m_vecFont[ nFontIndex ].Face;
bool bBold = m_vecFont[ nFontIndex ].nFontWeight*100 >= FW_BOLD;
SFontInfo& FontInfo = m_vecFont.at( nFontIndex );
vector<int> vecWidthList;
int nNumLine = WordBreak( strText, CaretKey, true, Face, bBold, FontInfo, fWidth, vecStrLine, vecWidthList, bUseRemainWidth );
nMaxWidth = 0;
for( int nLine=0; nLine<nNumLine; ++nLine )
{
int nWidth = vecWidthList.at( nLine );
if( nMaxWidth < nWidth )
nMaxWidth = nWidth;
}
vecWidthList.clear();
if( nNumLine == -1 )
return false;
return true;
}
void CEtFontMng::SetOriginWidth( float& fWidth )
{
fWidth = m_fOriginWidth;
}
int CEtFontMng::WordBreak( wstring& strText, SCaretKey& CaretKey, bool bAlreadyExistCaret, FT_Face& Face, bool bBold, SFontInfo& FontInfo,
float fWidth, vector<wstring>& vecStrLine, vector<int>& vecWidthList, bool bUseRemainWidth )
{
vector<wstring> vlWords;
vector<int> vlWordWidths;
vector<SCRIPT_LOGATTR> vecLogAttr;
if( s_bUseWordBreak )
{
GetWordBreakInfo( strText, vecLogAttr );
if( vecLogAttr.size() != strText.length() )
return -1;
int nWordStartPos = 0;
for( int i=0; i<static_cast<int>(vecLogAttr.size()); i++ )
{
if( vecLogAttr[i].fSoftBreak == 1 )
{
std::wstring strWord = strText.substr( nWordStartPos, i - nWordStartPos );
strWord = boost::algorithm::trim_copy( strWord );
if( static_cast<int>( strWord.length() ) > 0 )
vlWords.push_back( strWord );
nWordStartPos = i;
}
if( i == static_cast<int>(vecLogAttr.size()) - 1 ) // Word Break <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
{
std::wstring strWord = strText.substr( nWordStartPos, i - nWordStartPos + 1 );
strWord = boost::algorithm::trim_copy( strWord );
if( static_cast<int>( strWord.length() ) > 0 )
vlWords.push_back( strWord );
}
}
for( int i=0; i<static_cast<int>(vlWords.size()); ++i )
{
wstring& strWord = vlWords.at( i );
int iWordWidth = 0;
for( int k=0; k<static_cast<int>(strWord.size()); ++k )
{
wchar_t chWord = strWord.at( k );
iWordWidth += GetCachedCharAdvanceX( Face, FontInfo, chWord, bBold, 100 ); // iNowAdvance<63><65> ū <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><E2BCAD> <20><><EFBFBD><EFBFBD> Advance <20><><EFBFBD><EFBFBD> <20>ʿ<EFBFBD><CABF><EFBFBD>)
}
vlWordWidths.push_back( iWordWidth );
}
}
int nSentenceWidth = 0;
int nTextLength = (int)strText.length();
wstring strLineText;
int iNowWordIndex = -1;
for( int i=0; i<nTextLength; ++i )
{
int nWidth = static_cast<int>( fWidth );
if( fWidth - static_cast<float>( nWidth ) > 0.0f )
nWidth++; // float->int <20><>ȯ<EFBFBD><C8AF> <20>߸<EFBFBD><DFB8><EFBFBD> <20>ֱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ø<EFBFBD>
FT_ULong ch = strText.at( i );
if( i < nTextLength-2 )
{
if( ch == '\r' && (strText.at(i+1) == '\n') || ch == '\n' )
{
nSentenceWidth = 0;
strLineText += L"\n";
if( ch == '\r' && (strText.at(i+1) == '\n') )
++i;
continue;
}
}
int nAdvanceX = GetCachedCharAdvanceX( Face, FontInfo, (wchar_t)ch, bBold, 100 ); // iNowAdvance<63><65> ū <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><E2BCAD> <20><><EFBFBD><EFBFBD> Advance <20><><EFBFBD><EFBFBD> <20>ʿ<EFBFBD><CABF><EFBFBD>)
if( nAdvanceX < 0 )
continue;
bool bNowBlank = strText.at( i ) == ' ';
bool bOverFlowSentence = nSentenceWidth + nAdvanceX > nWidth;
if( s_bUseWordBreak && ( vecLogAttr[i].fSoftBreak && !vecLogAttr[i].fWhiteSpace ) )
{
iNowWordIndex++;
// <20><><EFBFBD><EFBFBD> <20>ܾ <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ܾ<EFBFBD><DCBE><EFBFBD> <20><><EFBFBD≯<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʺ<EFBFBD><CABA><EFBFBD> <20>ʰ<EFBFBD><CAB0>ϴ<EFBFBD><CFB4><EFBFBD> Ȯ<><C8AE>.
if( iNowWordIndex < static_cast<int>( vlWordWidths.size() ) )
{
int iWordWidth = vlWordWidths.at( iNowWordIndex );
int iNextWordIncludeSentenceWidth = nSentenceWidth + iWordWidth;
if( iNextWordIncludeSentenceWidth > (int)(fWidth + 0.005f) ) // <20>Ҽ<EFBFBD><D2BC><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٱ<EFBFBD><D9B1><EFBFBD><EFBFBD><EFBFBD> <20>ʺ<EFBFBD><CABA><EFBFBD> <20><>Ȯ<EFBFBD>ϰ<EFBFBD> <20>Ѱ<EFBFBD><D1B0><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>߸<EFBFBD> <20>Ǵܵ<C7B4> <20><> <20>־ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
bOverFlowSentence = true;
}
}
// <20>ʺ<EFBFBD><CABA><EFBFBD> <20>Ѿ<D1BE>ٸ<EFBFBD> new line ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD>ش<EFBFBD>.
if( bOverFlowSentence )
{
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ڰ<EFBFBD> <20><><EFBFBD><EFBFBD>ڸ<EFBFBD> <20><><EFBFBD>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD>.
if( bNowBlank )
{
strLineText += L"\n";
nSentenceWidth = 0;
}
else
{
strLineText += L"\n";
strLineText += strText.at( i );
nSentenceWidth = nAdvanceX;
}
if( bUseRemainWidth )
SetOriginWidth( fWidth );
continue;
}
strLineText += strText.at( i );
nSentenceWidth += nAdvanceX;
if( !bAlreadyExistCaret )
{
m_caretInfo[ CaretKey ].vecCaretPos.push_back( nSentenceWidth );
m_caretInfo[ CaretKey ].mapPosByCaret.insert( make_pair(nSentenceWidth, i+1) );
}
}
nTextLength = (int)strLineText.length();
int nLastNewLine = 0;
for( int i=0; i<nTextLength; ++i )
{
FT_ULong ch = strLineText.at( i );
// <20>ٹٲ<D9B9> <20>ڵ尡 <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \n <20>ϳ<EFBFBD><CFB3><EFBFBD> <20><><EFBFBD><20>ִ<EFBFBD>.
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ڿ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>־ \n <20><><EFBFBD><EFBFBD> <20>ٲ<EFBFBD><D9B2><EFBFBD> <20>ʵ<EFBFBD><CAB5><EFBFBD> <20>ϱ<EFBFBD> <20><><EFBFBD><EFBFBD> -2 <20><> ó<><C3B3>
if( ch == '\r' )
{
if( i+1 < nTextLength - 1 && strText.at( i+1 ) == '\n' )
{
std::wstring strWord = strLineText.substr( nLastNewLine, i-nLastNewLine );
// <20>ٹٲ<D9B9> ó<><C3B3>.
// \r <20><> \n <20><><EFBFBD>ڱ<EFBFBD><DAB1><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؾ<EFBFBD><D8BE>ϹǷ<CFB9> ī<><C4AB>Ʈ<EFBFBD><C6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD> -1 <20>ϰ<EFBFBD> LastNewLine<6E><65><EFBFBD><EFBFBD> +2 <20><><EFBFBD>ش<EFBFBD>
vecStrLine.push_back( strWord );
nLastNewLine = i + 2;
}
}
else if( ch == '\n' )
{
std::wstring strWord = strLineText.substr( nLastNewLine, i-nLastNewLine );
vecStrLine.push_back( strWord );
nLastNewLine = i + 1;
}
}
vlWords.clear();
vlWordWidths.clear();
vecLogAttr.clear();
if( vecStrLine.empty() )
{
vecStrLine.push_back( strText );
}
else // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><20><><EFBFBD><EFBFBD> <20><><EFBFBD>Ϳ<EFBFBD> <20>־<EFBFBD><D6BE>ش<EFBFBD>.
{
if( (int)strLineText.length() > nLastNewLine )
{
std::wstring strWord = strLineText.substr( nLastNewLine, (int)strLineText.length() - nLastNewLine );
vecStrLine.push_back( strWord );
}
}
int nNumLine = (int)vecStrLine.size();
// <20><><EFBFBD><EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD> <20>Ǿ<EFBFBD><C7BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ij<><C4B3> ij<><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. ij<><C4B3> ij<><C4B3><EFBFBD><EFBFBD> <20>־<EFBFBD><D6BE><EFBFBD> <20>̹<EFBFBD><CCB9><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ǵ<EFBFBD> <20><><EFBFBD>ڿ<EFBFBD><DABF><EFBFBD>
// <20>־<EFBFBD><D6BE><EFBFBD> <20>ʺ<EFBFBD><CABA><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD><ECBFA1> <20><><EFBFBD>ܵд<DCB5>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20>Ǹ<EFBFBD> ij<><C4B3> <20><>ġ<EFBFBD><C4A1><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
// <20>ǹ̰<C7B9> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>Ŀ<EFBFBD> <20>ʺ<EFBFBD><CABA><EFBFBD> <20>ٸ<EFBFBD><D9B8><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ڿ<EFBFBD>, <20><>Ʈ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> CalcTextRect -> GetCaretPos
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ǿ<EFBFBD> ij<>̵<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ǿ<EFBFBD><C7BE><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ڿ<EFBFBD><DABF><EFBFBD> <20>ʺ<EFBFBD><CABA><EFBFBD> <20><><EFBFBD>ϵDZ<CFB5> <20><><EFBFBD><EFBFBD><EFBFBD>̴<EFBFBD>. <20><><EFBFBD>ο<EFBFBD> <20>ʺ<EFBFBD><CABA><EFBFBD> <20><><EFBFBD>ڿ<EFBFBD><DABF><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ؾ<EFBFBD><D8BE><EFBFBD> <20><><EFBFBD><20><><EFBFBD><EFBFBD> <20>ʺ<EFBFBD><CABA><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>´<EFBFBD>. <20>̷<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ڿ<EFBFBD><DABF><EFBFBD> <20><><EFBFBD>ٿ<EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ij<><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
if( 1 < nNumLine )
m_caretInfo.erase( CaretKey );
for( int i=0; i<static_cast<int>(vecStrLine.size()); ++i )
{
wstring& strWord = vecStrLine.at( i );
int iWordWidth = 0;
for( int k=0; k<static_cast<int>(strWord.size()); ++k )
{
wchar_t chWord = strWord.at( k );
iWordWidth += GetCachedCharAdvanceX( Face, FontInfo, chWord, bBold, 100 );
}
vecWidthList.push_back( iWordWidth );
}
return nNumLine;
}