Files
core/ASCImageStudio3/ASCGraphics/Objects/Font/FontEngine.cpp

616 lines
18 KiB
C++

#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "FontEngine.h"
#include "FontFile.h"
#include "Font.h"
#include "FT_FontEngine.h"
#include "List.h"
//-------------------------------------------------------------------------------------------------------------------------------
// CFontEngine
//-------------------------------------------------------------------------------------------------------------------------------
CFontEngine::CFontEngine(BOOL bAntiAliasing, BOOL bUseKerning, BOOL bLoadWinFonts, CString sWinFontsXml, CString wsFontDir)
{
for ( int nIndex = 0; nIndex < MAX_FONT_CACHE_SIZE; ++nIndex )
{
m_pFontCache[nIndex] = NULL;
}
// Èíèöèàëèçèðóåì áèáëèîòåêó FreeType
m_pFreeTypeEngine = CFreeTypeFontEngine::Initialize( bAntiAliasing, bUseKerning );
// Ñîñòàâëÿåì ñïèñîê óñòàíîâëåííûõ øðèôòîâ
m_pWinFontList = NULL;
if ( _T("") != sWinFontsXml )
m_pWinFontList = new CWinFontList( sWinFontsXml );
else if ( bLoadWinFonts )
{
if ( _T("") != wsFontDir )
m_pWinFontList = new CWinFontList( m_pFreeTypeEngine->m_pLibrary, wsFontDir );
else
m_pWinFontList = new CWinFontList( m_pFreeTypeEngine->m_pLibrary );
}
m_pDefaultFont[0] = NULL;
m_pDefaultFont[1] = NULL;
m_pDefaultFont[2] = NULL;
m_pDefaultFont[3] = NULL;
for ( int nIndex = 0; nIndex < INSTALLED_FONTS_CACHE_SIZE; nIndex++ )
{
m_arrInstalledFontsCache[nIndex].wsFamilyName = _T("");
m_arrInstalledFontsCache[nIndex].lStyle = 0;
m_arrInstalledFontsCache[nIndex].pWinFontInfo = NULL;
}
}
CFontEngine::CFontEngine(BOOL bAntiAliasing, BOOL bUseKerning, BOOL bLoadWinFonts, BYTE* pBuffer, CString wsFontDir)
{
for ( int nIndex = 0; nIndex < MAX_FONT_CACHE_SIZE; ++nIndex )
{
m_pFontCache[nIndex] = NULL;
}
// Èíèöèàëèçèðóåì áèáëèîòåêó FreeType
m_pFreeTypeEngine = CFreeTypeFontEngine::Initialize( bAntiAliasing, bUseKerning );
// Ñîñòàâëÿåì ñïèñîê óñòàíîâëåííûõ øðèôòîâ
m_pWinFontList = NULL;
if ( NULL != pBuffer )
m_pWinFontList = new CWinFontList( pBuffer, wsFontDir );
else if ( bLoadWinFonts )
{
if ( _T("") != wsFontDir )
m_pWinFontList = new CWinFontList( m_pFreeTypeEngine->m_pLibrary, wsFontDir );
else
m_pWinFontList = new CWinFontList( m_pFreeTypeEngine->m_pLibrary );
}
m_pDefaultFont[0] = NULL;
m_pDefaultFont[1] = NULL;
m_pDefaultFont[2] = NULL;
m_pDefaultFont[3] = NULL;
for ( int nIndex = 0; nIndex < INSTALLED_FONTS_CACHE_SIZE; nIndex++ )
{
m_arrInstalledFontsCache[nIndex].wsFamilyName = _T("");
m_arrInstalledFontsCache[nIndex].lStyle = 0;
m_arrInstalledFontsCache[nIndex].pWinFontInfo = NULL;
}
}
CFontEngine::~CFontEngine()
{
for ( int nIndex = 0; nIndex < MAX_FONT_CACHE_SIZE; ++nIndex )
{
if ( m_pFontCache[nIndex] )
{
delete m_pFontCache[nIndex];
}
}
for ( int nIndex = 0; nIndex < 4; nIndex++ )
{
if ( m_pDefaultFont[nIndex] )
delete m_pDefaultFont[nIndex];
}
if ( m_pFreeTypeEngine )
{
delete m_pFreeTypeEngine;
}
if ( m_pWinFontList )
delete m_pWinFontList;
}
CFontFile *CFontEngine::GetFontFile(wchar_t *wsFamilyName, BOOL bBold, BOOL bItalic)
{
long lIndex = 0;
long lStyle = ( bBold ? 1 : 0 ) + ( bItalic ? 2 : 0 );
CWinFontInfo *pFontInfo = GetInstalledFont(wsFamilyName, lStyle, &lIndex );
if ( !pFontInfo )
return NULL;
for ( int nIndex = 0; nIndex < MAX_FONT_CACHE_SIZE; ++nIndex )
{
if ( m_pFontCache[nIndex] )
{
CFontFile *pFontFile = m_pFontCache[nIndex]->GetFontFile();
CStringW oTemp1 = pFontFile->m_wsFileName;
CStringW oTemp2 = pFontInfo->m_wsFontPath;
oTemp1.MakeLower();
oTemp2.MakeLower();
if ( pFontFile && oTemp1 == oTemp2 && pFontFile->m_lIndex == pFontInfo->m_lIndex )
{
return pFontFile;
}
}
}
return NULL;
}
CFontFile *CFontEngine::GetFontFile(wchar_t *wsFilePath, long lIndex)
{
for ( int nIndex = 0; nIndex < MAX_FONT_CACHE_SIZE; ++nIndex )
{
if ( m_pFontCache[nIndex] )
{
CFontFile *pFontFile = m_pFontCache[nIndex]->GetFontFile();
CStringW oTemp1 = pFontFile->m_wsFileName;
CStringW oTemp2 = CStringW( wsFilePath );
oTemp1.MakeLower();
oTemp2.MakeLower();
if ( pFontFile && oTemp1 == oTemp2 && pFontFile->m_lIndex == lIndex )
{
return pFontFile;
}
}
}
return NULL;
}
CFontFile *CFontEngine::LoadFont(wchar_t *wsFamilyName, BOOL bBold, BOOL bItalic)
{
long lIndex = 0;
long lStyle = ( bBold ? 1 : 0 ) + ( bItalic ? 2 : 0 );
CWinFontInfo *pFontInfo = GetInstalledFont(wsFamilyName, lStyle, &lIndex );
if ( !pFontInfo )
return NULL;
CFontFile *pFontFile = NULL;
if ( !pFontFile && m_pFreeTypeEngine )
{
pFontFile = m_pFreeTypeEngine->LoadFont( pFontInfo->m_wsFontPath.GetBuffer(), pFontInfo->m_lIndex );
}
return pFontFile;
}
CFontFile *CFontEngine::LoadFont(wchar_t *wsFilePath, long lIndex)
{
CFontFile *pFontFile = NULL;
if ( !pFontFile && m_pFreeTypeEngine )
{
pFontFile = m_pFreeTypeEngine->LoadFont( wsFilePath, lIndex );
}
return pFontFile;
}
CWinFontInfo *CFontEngine::GetInstalledFont(long lIndex)
{
if ( !m_pWinFontList )
return NULL;
int nCount = m_pWinFontList->GetFonts()->GetLength();
if ( lIndex < 0 )
lIndex = 0;
else if ( lIndex >= nCount )
lIndex = nCount - 1;
CWinFontInfo *pFontInfo = m_pWinFontList->GetByIndex( lIndex );
return pFontInfo;
}
CWinFontInfo *CFontEngine::GetInstalledFont(wchar_t *wsFamilyName, long lStyle, long *plIndex)
{
int nCacheIndex = FindInCache( wsFamilyName, lStyle );
if ( -1 != nCacheIndex )
return m_arrInstalledFontsCache[nCacheIndex].pWinFontInfo;
if ( !m_pWinFontList )
return NULL;
// Èùåì âñå øðèôòû ñ äàííûì èìåíåì FamilyName
CList *pFoundList = new CList();
CSimpleArray<int> arrIndexList;
if ( !pFoundList )
return NULL;
for ( int nIndex = 0; nIndex < m_pWinFontList->GetFonts()->GetLength(); nIndex++ )
{
CWinFontInfo *pFontInfo = m_pWinFontList->GetByIndex( nIndex );
if ( CStringW( wsFamilyName ) == pFontInfo->m_wsFontName )
{
// Ìû äîáàâëÿåì òîëüêî ññûëêè â ñïèñîê, ïîýòîìó ïðè óäàëåíèè íå íàäî äåëàòü DeleteCList()
pFoundList->Append( pFontInfo );
arrIndexList.Add( nIndex );
}
}
if ( pFoundList->GetLength() <= 0 )
{
delete pFoundList;
return NULL;
}
BOOL bBold = FALSE;
BOOL bItalic = FALSE;
switch (lStyle)
{
case FontConstants::FontStyleRegular: bBold = FALSE; bItalic = FALSE; break;
case FontConstants::FontStyleItalic: bBold = FALSE; bItalic = TRUE; break;
case FontConstants::FontStyleBold: bBold = TRUE; bItalic = FALSE; break;
case FontConstants::FontStyleBoldItalic: bBold = TRUE; bItalic = TRUE; break;
}
// Èùåì øðèôò ñ äàííûì ñòèëåì
int arrStyles[4] = { -1, -1, -1, -1 }; // { Regular, Bold, Italic, Bold Italic }
for ( int nIndex = 0; nIndex < pFoundList->GetLength(); nIndex++ )
{
CWinFontInfo *pCurFont = (CWinFontInfo *)pFoundList->GetByIndex( nIndex );
if ( arrStyles[3] < 0 && TRUE == pCurFont->m_bBold && TRUE == pCurFont->m_bItalic )
arrStyles[3] = nIndex;
if ( arrStyles[2] < 0 && FALSE == pCurFont->m_bBold && TRUE == pCurFont->m_bItalic )
arrStyles[2] = nIndex;
if ( arrStyles[1] < 0 && TRUE == pCurFont->m_bBold && FALSE == pCurFont->m_bItalic )
arrStyles[1] = nIndex;
if ( arrStyles[0] < 0 && FALSE == pCurFont->m_bBold && FALSE == pCurFont->m_bItalic )
arrStyles[0] = nIndex;
}
CWinFontInfo *pFontInfo = NULL;
BOOL bNeedBold = bBold, bNeedItalic = bItalic;
if ( bBold && bItalic && arrStyles[3] >= 0 )
{
pFontInfo = (CWinFontInfo *)pFoundList->GetByIndex( arrStyles[3] );
bNeedBold = FALSE;
bNeedItalic = FALSE;
*plIndex = arrIndexList.GetData()[arrStyles[3]];
}
else if ( bBold && bItalic && arrStyles[3] < 0 && arrStyles[1] >= 0 )
{
pFontInfo = (CWinFontInfo *)pFoundList->GetByIndex( arrStyles[1] );
bNeedBold = FALSE;
*plIndex = arrIndexList.GetData()[arrStyles[1]];
}
else if ( bBold && bItalic && arrStyles[3] < 0 && arrStyles[2] >= 0 )
{
pFontInfo = (CWinFontInfo *)pFoundList->GetByIndex( arrStyles[2] );
bNeedItalic = FALSE;
*plIndex = arrIndexList.GetData()[arrStyles[2]];
}
else if ( bBold && bItalic && arrStyles[3] < 0 && arrStyles[0] >= 0 )
{
pFontInfo = (CWinFontInfo *)pFoundList->GetByIndex( arrStyles[0] );
*plIndex = arrIndexList.GetData()[arrStyles[0]];
}
else if ( bBold && !bItalic && arrStyles[1] >= 0 )
{
pFontInfo = (CWinFontInfo *)pFoundList->GetByIndex( arrStyles[1] );
bNeedBold = FALSE;
*plIndex = arrIndexList.GetData()[arrStyles[1]];
}
else if ( bBold && !bItalic && arrStyles[1] < 0 && arrStyles[0] >= 0 )
{
pFontInfo = (CWinFontInfo *)pFoundList->GetByIndex( arrStyles[0] );
*plIndex = arrIndexList.GetData()[arrStyles[0]];
}
else if ( !bBold && bItalic && arrStyles[2] >= 0 )
{
pFontInfo = (CWinFontInfo *)pFoundList->GetByIndex( arrStyles[2] );
bNeedItalic = FALSE;
*plIndex = arrIndexList.GetData()[arrStyles[2]];
}
else if ( !bBold && bItalic && arrStyles[2] < 0 && arrStyles[0] >= 0 )
{
pFontInfo = (CWinFontInfo *)pFoundList->GetByIndex( arrStyles[0] );
*plIndex = arrIndexList.GetData()[arrStyles[0]];
}
else if ( !bBold && !bItalic && arrStyles[0] >= 0 )
{
pFontInfo = (CWinFontInfo *)pFoundList->GetByIndex( arrStyles[0] );
*plIndex = arrIndexList.GetData()[arrStyles[0]];
}
else
{
// åñëè íå îäèí èç ïðåäûäóùèõ âàðèàíòîâ íå ïðîøåë, òîãäà áåðåì ïåðâûé ïîïàâøèéñÿ ôîíò
// çàïîìèíàÿ, íóæíî ëè â áóäóùåì äåëàòü Bold è Italic
int nIndex = 0;
for ( ; nIndex < 4; nIndex++ )
if ( arrStyles[nIndex] >= 0 )
break;
if ( nIndex < 4 )
{
switch ( nIndex )
{
case 0: break;
case 1: bNeedBold = FALSE; break;
case 2: bNeedItalic = FALSE; break;
case 3: bNeedItalic = FALSE; bNeedBold = FALSE; break;
}
pFontInfo = (CWinFontInfo *)pFoundList->GetByIndex( arrStyles[nIndex] );
*plIndex = arrIndexList.GetData()[arrStyles[nIndex]];
}
}
delete pFoundList;
TInstalledFontCacheEntry oEntry;
oEntry.lStyle = lStyle;
oEntry.pWinFontInfo = pFontInfo;
oEntry.wsFamilyName = CStringW( wsFamilyName );
AddToCache( oEntry );
return pFontInfo;
}
CWinFontInfo *CFontEngine::GetInstalledFont(CString sParamsXml)
{
if ( !m_pWinFontList )
return NULL;
return m_pWinFontList->GetByParams( sParamsXml );
}
CWinFontInfo *CFontEngine::GetInstalledFont(wchar_t* wsAltFontName, long lCharset, wchar_t* wsFamilyClass, long lStyle, BOOL bFixed, wchar_t *wsPanose, long lUnicodeRange1, long lUnicodeRange2, long lUnicodeRange3, long lUnicodeRange4, long lCodePageRange1, long lCodePageRange2, long lAvgWidth)
{
if ( !m_pWinFontList )
return NULL;
return m_pWinFontList->GetByParams( wsAltFontName, lCharset, wsFamilyClass, lStyle, bFixed, wsPanose, lUnicodeRange1, lUnicodeRange2, lUnicodeRange3, lUnicodeRange4, lCodePageRange1, lCodePageRange2, lAvgWidth );
}
long CFontEngine::GetInstalledFontsCount()
{
if ( !m_pWinFontList )
return 0;
return m_pWinFontList->GetFonts()->GetLength();
}
BOOL CFontEngine::IsStyleAvailable(wchar_t *wsFamilyName, long lStyle)
{
if ( !m_pWinFontList )
return FALSE;
BOOL bResult = FALSE;
BOOL bBold = FALSE;
BOOL bItalic = FALSE;
switch (lStyle)
{
case FontConstants::FontStyleRegular: bBold = FALSE; bItalic = FALSE; break;
case FontConstants::FontStyleItalic: bBold = FALSE; bItalic = TRUE; break;
case FontConstants::FontStyleBold: bBold = TRUE; bItalic = FALSE; break;
case FontConstants::FontStyleBoldItalic: bBold = TRUE; bItalic = TRUE; break;
}
// Èùåì âñå øðèôòû ñ äàííûì èìåíåì FamilyName
CList *pFoundList = new CList();
if ( !pFoundList )
return FALSE;
for ( int nIndex = 0; nIndex < m_pWinFontList->GetFonts()->GetLength(); nIndex++ )
{
CWinFontInfo *pFontInfo = m_pWinFontList->GetByIndex( nIndex );
if ( CStringW( wsFamilyName ) == pFontInfo->m_wsFontName )
{
// Ìû äîáàâëÿåì òîëüêî ññûëêè â ñïèñîê, ïîýòîìó ïðè óäàëåíèè íå íàäî äåëàòü DeleteCList()
pFoundList->Append( pFontInfo );
}
}
// Èùåì øðèôò ñ äàííûì ñòèëåì
int arrStyles[4] = { -1, -1, -1, -1 }; // { Regular, Bold, Italic, Bold Italic }
for ( int nIndex = 0; nIndex < pFoundList->GetLength(); nIndex++ )
{
CWinFontInfo *pCurFont = (CWinFontInfo *)pFoundList->GetByIndex( nIndex );
if ( arrStyles[3] < 0 && TRUE == pCurFont->m_bBold && TRUE == pCurFont->m_bItalic )
arrStyles[3] = nIndex;
if ( arrStyles[2] < 0 && FALSE == pCurFont->m_bBold && TRUE == pCurFont->m_bItalic )
arrStyles[2] = nIndex;
if ( arrStyles[1] < 0 && TRUE == pCurFont->m_bBold && FALSE == pCurFont->m_bItalic )
arrStyles[1] = nIndex;
if ( arrStyles[0] < 0 && FALSE == pCurFont->m_bBold && FALSE == pCurFont->m_bItalic )
arrStyles[0] = nIndex;
}
if ( arrStyles[0] >= 0 ) // Åñëè åñòü Regular, òî â êðàéíåì ñëó÷àå îñòàëüíûå èç íåãî ìîæåì ïîëó÷èòü ñ ïîìîùüþ ïðåîáðàçîâàíèé
bResult = TRUE;
else if ( FALSE == bBold && FALSE == bItalic ) // Regular íåëüçÿ ïîëó÷èòü èç äðóãèõ ñòèëåé
bResult = FALSE;
else if ( TRUE == bBold && FALSE == bItalic )
{
if ( arrStyles[1] >= 0 )
bResult = TRUE;
else
bResult = FALSE;
}
else if ( FALSE == bBold && TRUE == bItalic )
{
if ( arrStyles[2] >= 0 )
bResult = TRUE;
else
bResult = FALSE;
}
else if ( TRUE == bBold && TRUE == bItalic )
{
if ( arrStyles[1] >= 0 || arrStyles[2] >= 0 || arrStyles[3] >= 0 )
bResult = TRUE;
else
bResult = FALSE;
}
return bResult;
}
CFont *CFontEngine::GetFont(CFontFile *pFontFile)
{
// Åñëè øðèôò ñîâïàäàåò ñ ïåðâûì â êýøå, òîãäà îòäàåì óêàçàòåëü íà ïåðâûé øðèôò
CFont *pFont = m_pFontCache[0];
if ( pFont && pFont->Matches( pFontFile ) )
{
return pFont;
}
// Åñëè øðèôò ñîâïàäàåò ñ íå ïåðâûì øðèôòîì èç êýøà, òîãäà óêàçàòåëü íà äàííûé øðèôò äâèãàåì â íà÷àëî êýøà è îòäàåì åãî
for ( int nFontIndex = 1; nFontIndex < MAX_FONT_CACHE_SIZE; ++nFontIndex )
{
pFont = m_pFontCache[nFontIndex];
if ( pFont && pFont->Matches( pFontFile ) )
{
for ( int nJ = nFontIndex; nJ > 0; --nJ )
{
m_pFontCache[nJ] = m_pFontCache[nJ - 1];
}
m_pFontCache[0] = pFont;
return pFont;
}
}
// Åñëè äàííîãî øðèôòà â êýøå íåò, ñîçäàåì øðèôò è çàïèñûâàåì åãî â íà÷àëî êýøà, à ïîñëåäíèé øðèôò èç êýøà óäàëÿåì(åñëè îí òàì åñòü)
pFont = pFontFile->MakeFont();
if ( m_pFontCache[MAX_FONT_CACHE_SIZE - 1] )
{
delete m_pFontCache[MAX_FONT_CACHE_SIZE - 1];
}
for ( int nJ = MAX_FONT_CACHE_SIZE - 1; nJ > 0; --nJ )
{
m_pFontCache[nJ] = m_pFontCache[nJ - 1];
}
m_pFontCache[0] = pFont;
return pFont;
}
void CFontEngine::SetAA(BOOL bAA)
{
m_pFreeTypeEngine->m_bAntiAliasing = bAA;
}
void CFontEngine::SetDefaultFont(wchar_t *wsFamilyName)
{
for ( int nIndex = 0; nIndex < 4; nIndex++ )
{
BOOL bBold, bItalic;
switch( nIndex )
{
case 0: bBold = FALSE; bItalic = FALSE; break;
case 1: bBold = TRUE; bItalic = FALSE; break;
case 2: bBold = FALSE; bItalic = TRUE; break;
case 3: bBold = TRUE; bItalic = TRUE; break;
}
long lIndex = 0;
long lStyle = ( bBold ? 1 : 0 ) + ( bItalic ? 2 : 0 );
CWinFontInfo *pFontInfo = GetInstalledFont(wsFamilyName, lStyle, &lIndex );
if ( !pFontInfo )
return;
CFontFile *pFontFile = NULL;
if ( !pFontFile && m_pFreeTypeEngine )
{
pFontFile = m_pFreeTypeEngine->LoadFont( pFontInfo->m_wsFontPath.GetBuffer(), pFontInfo->m_lIndex );
}
if ( !pFontFile )
return;
if ( m_pDefaultFont[nIndex] )
delete m_pDefaultFont[nIndex];
if ( 0 == nIndex && m_pWinFontList )
m_pWinFontList->SetDefaultFont( lIndex );
m_pDefaultFont[nIndex] = pFontFile->MakeFont();
UpdateStyles( m_pDefaultFont[nIndex], bBold, bItalic );
}
}
void CFontEngine::SetDefaultFont(wchar_t *wsFilePath, long lIndex)
{
for ( int nIndex = 0; nIndex < 4; nIndex++ )
{
BOOL bBold, bItalic;
switch( nIndex )
{
case 0: bBold = FALSE; bItalic = FALSE; break;
case 1: bBold = TRUE; bItalic = FALSE; break;
case 2: bBold = FALSE; bItalic = TRUE; break;
case 3: bBold = TRUE; bItalic = TRUE; break;
}
CFontFile *pFontFile = NULL;
if ( !pFontFile && m_pFreeTypeEngine )
{
pFontFile = m_pFreeTypeEngine->LoadFont( wsFilePath, lIndex );
}
if ( !pFontFile )
return;
if ( m_pDefaultFont[nIndex] )
delete m_pDefaultFont[nIndex];
m_pDefaultFont[nIndex] = pFontFile->MakeFont();
UpdateStyles( m_pDefaultFont[nIndex], bBold, bItalic );
}
}
CFont *CFontEngine::GetDefaultFont(BOOL bBold, BOOL bItalic)
{
int nIndex = ( bBold ? 1 : 0 ) + ( bItalic ? 2 : 0 );
return m_pDefaultFont[nIndex];
}
void CFontEngine::AddToCache(TInstalledFontCacheEntry oEntry)
{
int nLastIndex = 0;
while ( nLastIndex < INSTALLED_FONTS_CACHE_SIZE && m_arrInstalledFontsCache[nLastIndex].wsFamilyName != _T("") )
nLastIndex++;
if ( INSTALLED_FONTS_CACHE_SIZE == nLastIndex )
{
for ( int nIndex = INSTALLED_FONTS_CACHE_SIZE - 1; nIndex > 0; nIndex-- )
{
m_arrInstalledFontsCache[nIndex] = m_arrInstalledFontsCache[nIndex - 1];
}
m_arrInstalledFontsCache[0] = oEntry;
}
else
{
m_arrInstalledFontsCache[nLastIndex] = oEntry;
}
}
int CFontEngine::FindInCache(wchar_t *wsFamilyName, long lStyle)
{
int nResult = -1;
for ( int nIndex = 0; nIndex < INSTALLED_FONTS_CACHE_SIZE; nIndex++ )
{
if ( _T("") == m_arrInstalledFontsCache[nIndex].wsFamilyName )
break;
if ( CStringW( wsFamilyName) == m_arrInstalledFontsCache[nIndex].wsFamilyName && lStyle == m_arrInstalledFontsCache[nIndex].lStyle )
{
nResult = nIndex;
break;
}
}
return nResult;
}