2476 lines
No EOL
76 KiB
C++
2476 lines
No EOL
76 KiB
C++
#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;
|
||
} |