Files
core/ASCImageStudio3/ASCGraphics/Objects/Font/WinFont.h
Oleg.Korshul 3a16812603 (1.0.1.177) подбор шривтов с использованием словаря
git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@56344 954022d7-b5bf-4e40-9824-e11837661b57
2016-05-20 22:55:15 +03:00

2104 lines
64 KiB
C++

#ifndef _WIN_FONT_H
#define _WIN_FONT_H
#include <shlobj.h>
#include "List.h"
#include "FontUtils.h"
#include "../../../../Common/XmlUtils.h"
#include "freetype\ftsnames.h"
#include "freetype\tttables.h"
#include "freetype\ftxf86.h"
#include "TimeMeasurer.h"
#include "../../../../DesktopEditor/freetype_names/FontMaps/FontDictionaryWorker.h"
static _bstr_t g_cpszXML_Font_Name = L"name";
static _bstr_t g_cpszXML_Font_Bold = L"bold";
static _bstr_t g_cpszXML_Font_Italic = L"italic";
static _bstr_t g_cpszXML_Font_Path = L"path";
static _bstr_t g_cpszXML_Font_Index = L"index";
static LONG g_lSizeofLONG = sizeof(LONG);
static LONG g_lSizeofBOOL = sizeof(BOOL);
static LONG g_lSizeofWCHAR = sizeof(WCHAR);
static LONG g_lSizeofULONG = sizeof(ULONG);
static LONG g_lSizeofUSHORT = sizeof(USHORT);
static LONG g_lSizeofSHORT = sizeof(SHORT);
//-------------------------------------------------------------------------------------------------------------------------------
// CWinFontInfo
//-------------------------------------------------------------------------------------------------------------------------------
enum EFontFormat
{
fontWindowsFNT = 0, // *.fon
fontTrueType = 1, // *.ttf
fontOpenType = 2, // *.ttf, *.otf (CFF ôîðìàò)
fontUnknown = 3
};
class CWinFontInfo
{
public:
CWinFontInfo(const CStringW &wsFontName, const CStringW &wsStyle, const CString &wsFontPath, long lIndex, BOOL bBold, BOOL bItalic, BOOL bFixedWidth, BYTE *pPanose, ULONG ulRange1, ULONG ulRange2, ULONG ulRange3, ULONG ulRange4, ULONG ulCodeRange1, ULONG ulCodeRange2, USHORT usWeigth, USHORT usWidth, SHORT sFamilyClass, EFontFormat eFormat, SHORT shAvgCharWidth, SHORT shAscent, SHORT shDescent, SHORT shLineGap, SHORT shXHeight, SHORT shCapHeight)
{
m_wsFontName = wsFontName;
m_wsFontPath = wsFontPath;
m_wsStyle = wsStyle;
m_lIndex = lIndex;
m_bBold = bBold;
m_bItalic = bItalic;
m_bIsFixed = bFixedWidth;
if ( pPanose )
memcpy( (void*)m_aPanose, (const void *)pPanose, 10 );
else
memset( (void*)m_aPanose, 0x00, 10 );
m_ulUnicodeRange1 = ulRange1;
m_ulUnicodeRange2 = ulRange2;
m_ulUnicodeRange3 = ulRange3;
m_ulUnicodeRange4 = ulRange4;
m_ulCodePageRange1 = ulCodeRange1;
m_ulCodePageRange2 = ulCodeRange2;
m_usWeigth = usWeigth;
m_usWidth = usWidth;
m_sFamilyClass = sFamilyClass;
m_eFontFormat = eFormat;
m_shAvgCharWidth = shAvgCharWidth;
m_shAscent = shAscent;
m_shDescent = shDescent;
m_shLineGap = shLineGap;
m_shXHeight = shXHeight;
m_shCapHeight = shCapHeight;
}
CWinFontInfo(BSTR wsFontName, BSTR wsFontPath, const long& lIndex, const BOOL& bBold, const BOOL& bItalic, const BOOL& bFixedWidth, BYTE *pPanose, const ULONG& ulRange1, const ULONG& ulRange2, const ULONG& ulRange3, const ULONG& ulRange4, const ULONG& ulCodeRange1, const ULONG& ulCodeRange2, const USHORT& usWeigth, const USHORT& usWidth, const SHORT& sFamilyClass, EFontFormat eFormat, const SHORT& shAvgCharWidth, const SHORT& shAscent, const SHORT& shDescent, const SHORT& shLineGap, const SHORT& shXHeight, const SHORT& shCapHeight)
{
m_wsFontName = wsFontName;
m_wsFontPath = wsFontPath;
m_wsStyle = L"";
m_lIndex = lIndex;
m_bBold = bBold;
m_bItalic = bItalic;
m_bIsFixed = bFixedWidth;
if ( pPanose )
memcpy( (void*)m_aPanose, (const void *)pPanose, 10 );
else
memset( (void*)m_aPanose, 0x00, 10 );
m_ulUnicodeRange1 = ulRange1;
m_ulUnicodeRange2 = ulRange2;
m_ulUnicodeRange3 = ulRange3;
m_ulUnicodeRange4 = ulRange4;
m_ulCodePageRange1 = ulCodeRange1;
m_ulCodePageRange2 = ulCodeRange2;
m_usWeigth = usWeigth;
m_usWidth = usWidth;
m_sFamilyClass = sFamilyClass;
m_eFontFormat = eFormat;
m_shAvgCharWidth = shAvgCharWidth;
m_shAscent = shAscent;
m_shDescent = shDescent;
m_shLineGap = shLineGap;
m_shXHeight = shXHeight;
m_shCapHeight = shCapHeight;
}
virtual ~CWinFontInfo()
{
}
BOOL Equals(CWinFontInfo *pFontInfo)
{
return ( m_wsFontName == pFontInfo->m_wsFontName && m_wsStyle == pFontInfo->m_wsStyle && m_wsFontPath == pFontInfo->m_wsFontPath && m_bItalic == pFontInfo->m_bItalic && m_bBold == pFontInfo->m_bBold );
}
void WriteToXml(XmlUtils::CXmlWriter *pWriter)
{
FromXmlString( m_wsFontName );
FromXmlString( m_wsFontPath );
pWriter->WriteNodeBegin( _T("WinFontEntry"), TRUE );
pWriter->WriteAttribute( _T("name"), m_wsFontName );
pWriter->WriteAttribute( _T("bold"), (int)m_bBold );
pWriter->WriteAttribute( _T("italic"), (int)m_bItalic );
pWriter->WriteAttribute( _T("path"), m_wsFontPath );
pWriter->WriteAttribute( _T("index"), (int)m_lIndex );
pWriter->WriteNodeEnd( _T("WinFontEntry"), TRUE );
}
inline static BSTR GetAttribute(XML::IXMLDOMNamedNodeMapPtr pAttributes, _bstr_t& bsName)
{
IXMLDOMNodePtr tempNode = pAttributes->getNamedItem(bsName);
if (NULL == tempNode)
return NULL;
BSTR bsValue;
tempNode->get_text(&bsValue);
return bsValue;
}
static CWinFontInfo *FromXml(XmlUtils::CXmlNode oNode)
{
if ( _T("WinFontEntry") == oNode.GetName() )
{
XML::IXMLDOMNamedNodeMapPtr pAttributes = oNode.GetAttributes();
BSTR bsBold = GetAttribute(pAttributes, g_cpszXML_Font_Bold);
BSTR bsItalic = GetAttribute(pAttributes, g_cpszXML_Font_Italic);
BSTR bsIndex = GetAttribute(pAttributes, g_cpszXML_Font_Index);
BOOL bBold = (BOOL)XmlUtils::GetInteger(bsBold);
BOOL bItalic = (BOOL)XmlUtils::GetInteger(bsItalic);
BSTR sName = GetAttribute(pAttributes, g_cpszXML_Font_Name);
BSTR sPath = GetAttribute(pAttributes, g_cpszXML_Font_Path);
long lIndex = (long)XmlUtils::GetInteger(bsIndex);
CWinFontInfo* pInfo = new CWinFontInfo( sName, sPath, lIndex, bBold, bItalic, FALSE, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, (EFontFormat)0, 0, 0, 0, 0, 0, 0 );
SysFreeString(bsBold);
SysFreeString(bsItalic);
SysFreeString(bsIndex);
SysFreeString(sName);
SysFreeString(sPath);
return pInfo;
}
return NULL;
}
static CWinFontInfo* FromBuffer(BYTE*& pBuffer, CString strFontDir)
{
// name
LONG lLen = *((LONG*)pBuffer);
pBuffer += g_lSizeofLONG;
BSTR bsName = (BSTR)pBuffer;
pBuffer += lLen;
// path
lLen = *((LONG*)pBuffer);
pBuffer += g_lSizeofLONG;
BSTR bsPath = (BSTR)pBuffer;
pBuffer += lLen;
// index
LONG lIndex = *((LONG*)pBuffer);
pBuffer += g_lSizeofLONG;
// italic
BOOL bItalic = *((BOOL*)pBuffer);
pBuffer += g_lSizeofBOOL;
// bold
BOOL bBold = *((BOOL*)pBuffer);
pBuffer += g_lSizeofBOOL;
// FixedWidth
BOOL bFixedWidth = *((BOOL*)pBuffer);
pBuffer += g_lSizeofBOOL;
// Panose
lLen = *((LONG*)pBuffer); // äîëæíî áûòü ðàâíî 10
pBuffer += g_lSizeofLONG;
BYTE pPanose[10];
memcpy( (void *)pPanose, (const void *)pBuffer, 10 );
pBuffer += lLen;
// ulUnicodeRange1
ULONG ulRange1 = *((ULONG*)pBuffer);
pBuffer += g_lSizeofULONG;
// ulUnicodeRange2
ULONG ulRange2 = *((ULONG*)pBuffer);
pBuffer += g_lSizeofULONG;
// ulUnicodeRange3
ULONG ulRange3 = *((ULONG*)pBuffer);
pBuffer += g_lSizeofULONG;
// ulUnicodeRange4
ULONG ulRange4 = *((ULONG*)pBuffer);
pBuffer += g_lSizeofULONG;
// ulCodePageRange1
ULONG ulCodeRange1 = *((ULONG*)pBuffer);
pBuffer += g_lSizeofULONG;
// ulCodePageRange2
ULONG ulCodeRange2 = *((ULONG*)pBuffer);
pBuffer += g_lSizeofULONG;
// usWeightClass
USHORT usWeight = *((USHORT*)pBuffer);
pBuffer += g_lSizeofUSHORT;
// usWidthClass
USHORT usWidth = *((USHORT*)pBuffer);
pBuffer += g_lSizeofUSHORT;
// sFamilyClass
SHORT sFamilyClass = *((SHORT*)pBuffer);
pBuffer += g_lSizeofSHORT;
// FontFormat
SHORT sFormat = *((SHORT*)pBuffer);
pBuffer += g_lSizeofSHORT;
// AvgCharWidth
SHORT shAvgCharWidth = *((SHORT*)pBuffer);
pBuffer += g_lSizeofSHORT;
// Ascent
SHORT shAscent = *((SHORT*)pBuffer);
pBuffer += g_lSizeofSHORT;
// Descent
SHORT shDescent = *((SHORT*)pBuffer);
pBuffer += g_lSizeofSHORT;
// LineGap
SHORT shLineGap = *((SHORT*)pBuffer);
pBuffer += g_lSizeofSHORT;
// XHeight
SHORT shXHeight = *((SHORT*)pBuffer);
pBuffer += g_lSizeofSHORT;
// CapHeight
SHORT shCapHeight = *((SHORT*)pBuffer);
pBuffer += g_lSizeofSHORT;
CStringW strPath = (CStringW)bsPath;
strPath = strFontDir + strPath;
bsPath = strPath.AllocSysString();
CWinFontInfo* pInfo = new CWinFontInfo( bsName, bsPath, lIndex, bBold, bItalic, bFixedWidth, (BYTE*)pPanose, ulRange1, ulRange2, ulRange3, ulRange4, ulCodeRange1, ulCodeRange2, usWeight, usWidth, sFamilyClass, (EFontFormat)sFormat, shAvgCharWidth, shAscent, shDescent, shLineGap, shXHeight, shCapHeight );
SysFreeString(bsPath);
return pInfo;
}
LONG GetBufferLen(CString strDirectory = _T(""))
{
CStringW sPath = m_wsFontPath;
if (0 != strDirectory.GetLength())
{
if (0 == sPath.Find(strDirectory))
{
sPath = sPath.Mid(strDirectory.GetLength());
}
}
return 4 * g_lSizeofLONG + 3 * g_lSizeofBOOL + (m_wsFontName.GetLength() + sPath.GetLength() + 2) * g_lSizeofWCHAR + 2 * g_lSizeofUSHORT + 6 * g_lSizeofULONG + 10 + 8 * g_lSizeofSHORT;
}
void ToBuffer(BYTE*& pBuffer, CString strDirectory = _T(""))
{
// name
LONG lLen = (m_wsFontName.GetLength() + 1) * g_lSizeofWCHAR;
*((LONG*)(pBuffer)) = lLen;
pBuffer += g_lSizeofLONG;
memcpy(pBuffer, m_wsFontName.GetBuffer(), lLen);
pBuffer += lLen;
// path
CStringW sPath = m_wsFontPath;
if (0 != strDirectory.GetLength())
{
if (0 == sPath.Find(strDirectory))
{
sPath = sPath.Mid(strDirectory.GetLength());
}
}
lLen = (sPath.GetLength() + 1) * g_lSizeofWCHAR;
*((LONG*)(pBuffer)) = lLen;
pBuffer += g_lSizeofLONG;
memcpy(pBuffer, sPath.GetBuffer(), lLen);
pBuffer += lLen;
// index
*((LONG*)(pBuffer)) = m_lIndex;
pBuffer += g_lSizeofLONG;
// italic
*((BOOL*)(pBuffer)) = m_bItalic;
pBuffer += g_lSizeofBOOL;
// bold
*((BOOL*)(pBuffer)) = m_bBold;
pBuffer += g_lSizeofBOOL;
// FixedWidth
*((BOOL*)pBuffer) = m_bIsFixed;
pBuffer += g_lSizeofBOOL;
// Panose
lLen = 10;
*((LONG*)(pBuffer)) = lLen;
pBuffer += g_lSizeofLONG;
memcpy( (void *)pBuffer, (const void *)m_aPanose, lLen );
pBuffer += lLen;
// ulUnicodeRange1
*((ULONG*)pBuffer) = m_ulUnicodeRange1;
pBuffer += g_lSizeofULONG;
// ulUnicodeRange2
*((ULONG*)pBuffer) = m_ulUnicodeRange2;
pBuffer += g_lSizeofULONG;
// ulUnicodeRange3
*((ULONG*)pBuffer) = m_ulUnicodeRange3;
pBuffer += g_lSizeofULONG;
// ulUnicodeRange4
*((ULONG*)pBuffer) = m_ulUnicodeRange4;
pBuffer += g_lSizeofULONG;
// ulCodePageRange1
*((ULONG*)pBuffer) = m_ulCodePageRange1;
pBuffer += g_lSizeofULONG;
// ulCodePageRange2
*((ULONG*)pBuffer) = m_ulCodePageRange2;
pBuffer += g_lSizeofULONG;
// usWeightClass
*((USHORT*)pBuffer) = m_usWeigth;
pBuffer += g_lSizeofUSHORT;
// usWidthClass
*((USHORT*)pBuffer) = m_usWidth;
pBuffer += g_lSizeofUSHORT;
// sFamilyClass
*((SHORT*)pBuffer) = m_sFamilyClass;
pBuffer += g_lSizeofSHORT;
// FontFormat
*((SHORT*)pBuffer) = (SHORT)m_eFontFormat;
pBuffer += g_lSizeofSHORT;
// AvgCharWidth
*((SHORT*)pBuffer) = (SHORT)m_shAvgCharWidth;
pBuffer += g_lSizeofSHORT;
// Ascent
*((SHORT*)pBuffer) = (SHORT)m_shAscent;
pBuffer += g_lSizeofSHORT;
// Descent
*((SHORT*)pBuffer) = (SHORT)m_shDescent;
pBuffer += g_lSizeofSHORT;
// LineGap
*((SHORT*)pBuffer) = (SHORT)m_shLineGap;
pBuffer += g_lSizeofSHORT;
// XHeight
*((SHORT*)pBuffer) = (SHORT)m_shXHeight;
pBuffer += g_lSizeofSHORT;
// CapHeight
*((SHORT*)pBuffer) = (SHORT)m_shCapHeight;
pBuffer += g_lSizeofSHORT;
}
static void FromXmlString(CString& strText)
{
strText.Replace(_T("&apos;"), _T("'"));
strText.Replace(_T("&lt;"), _T("<"));
strText.Replace(_T("&gt;"), _T(">"));
strText.Replace(_T("&quot;"), _T("\""));
strText.Replace(_T("&amp;"), _T("&"));
}
public:
CStringW m_wsFontName; // Èìÿ øðèôòà
CStringW m_wsFontPath; // Ïóòü ê ôàéëó ñ øðèôòîì
long m_lIndex; // Íîìåð øðèôòà â ôàéëå(åñëè â ôàéëå áîëüøå 1 øðèôòà)
CStringW m_wsStyle;
BOOL m_bBold; // Bold text
BOOL m_bItalic; // Italic text
BOOL m_bIsFixed; // Ìîíîøèðèííûé øðèôò?
BYTE m_aPanose[10];
ULONG m_ulUnicodeRange1; // Bits 0-31
ULONG m_ulUnicodeRange2; // Bits 32-63
ULONG m_ulUnicodeRange3; // Bits 64-95
ULONG m_ulUnicodeRange4; // Bits 96-127
ULONG m_ulCodePageRange1; // Bits 0-31
ULONG m_ulCodePageRange2; // Bits 32-63
USHORT m_usWeigth;
USHORT m_usWidth;
SHORT m_sFamilyClass;
EFontFormat m_eFontFormat;
SHORT m_shAvgCharWidth; // Ñðåäíÿÿ øèðèíà ñèìâîëîâ
SHORT m_shAscent; // Ascent
SHORT m_shDescent; // Descent
SHORT m_shLineGap; // Ìåæñèìâîëüíûé èíòåðâàë
SHORT m_shXHeight; // Âûñîòà áóêâû 'x' (â íèæíåì ðåãèñòðå)
SHORT m_shCapHeight; // Âûñîòà áóêâû 'H' (â âåðõíåì ðåãèñòðå)
};
//-------------------------------------------------------------------------------------------------------------------------------
// CWinFontList
//-------------------------------------------------------------------------------------------------------------------------------
class CWinFontList
{
public:
CWinFontList(FT_Library pLibrary)
{
m_lDefIndex = -1;
m_pFonts = new CList();
// Èùåì äèðåêòîðèþ ñ ôîíòàìè (îáû÷íî ýòî C:\Windows\Fonts)
m_wsWinFontDir[0] = '\0';
if ( !SHGetSpecialFolderPathW( NULL, m_wsWinFontDir, CSIDL_FONTS, FALSE ) )
m_wsWinFontDir[0] = '\0';
OSVERSIONINFO oVersion;
oVersion.dwOSVersionInfoSize = sizeof(oVersion);
GetVersionEx( &oVersion );
wchar_t wsPath[1000];
if ( oVersion.dwPlatformId == VER_PLATFORM_WIN32_NT )
_tcscpy_s( wsPath, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts\\") );
else
_tcscpy_s( wsPath, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts\\") );
TCHAR szName[2 * MAX_PATH];
TCHAR szData[2 * MAX_PATH];
while ( GetNextNameValue( HKEY_LOCAL_MACHINE, wsPath, szName, szData ) == ERROR_SUCCESS)
{
int nError = 0;
FT_Face pFace = NULL;
CStringW wsFilePath( szData );
if ( nError = FT_New_FaceW( pLibrary, wsFilePath.GetBuffer(), 0, &pFace ) )
{
wsFilePath = CStringW( m_wsWinFontDir ) + CStringW( _T("\\") ) + CStringW( szData );
wsFilePath.Replace( _T("\0"), _T("") );
if ( nError = FT_New_FaceW( pLibrary, wsFilePath.GetBuffer(), 0, &pFace ) )
{
wsPath[0] = _T('\0');
continue;
}
}
// TO DO: Øðèôòû, êîòîðûå íåëüçÿ ñêåéëèòü (ò.å. èçìåíÿòü ðàçìåð
// ïðîèçâîëüíî) ìû íå ãðóçèì. Âîçìîæíî â áóäóùåì íàäî áóäåò
// ñäåëàòü, ÷òîáû ðàáîòàë è òàêîé âàðèàíò. (â Word òàêèå øðèôòû
// íå èñïîëüçóþòñÿ)
if ( !( pFace->face_flags & FT_FACE_FLAG_SCALABLE ) )
{
FT_Done_Face( pFace );
wsPath[0] = _T('\0');
continue;
}
int nFacesCount = pFace->num_faces;
if ( nError = FT_Done_Face( pFace ) )
{
wsPath[0] = _T('\0');
continue;
}
for ( int nIndex = 0; nIndex < nFacesCount; nIndex++ )
{
if ( FT_New_FaceW( pLibrary, wsFilePath.GetBuffer(), nIndex, &pFace ) )
{
wsPath[0] = _T('\0');
continue;
}
BOOL bBold = ( pFace->style_flags & FT_STYLE_FLAG_BOLD ? 1 : 0 );
BOOL bItalic = pFace->style_flags & FT_STYLE_FLAG_ITALIC;
CStringW wsPostscriptName = CStringW( FT_Get_Postscript_Name( pFace ) );
//if ( wsPostscriptName.GetLength() <= 0 )
// CStringW wsPostscriptName = CStringW( (char*)pFace->family_name );
int nNamesCount = FT_Get_Sfnt_Name_Count( pFace );
for ( int nNameIndex = 0; nNameIndex < nNamesCount; nNameIndex++ )
{
FT_SfntName_ oSfntName;
FT_Get_Sfnt_Name( pFace, nNameIndex, &oSfntName );
if ( oSfntName.language_id == 0x0409 && oSfntName.name_id == 1 && oSfntName.platform_id == 3 )
{
// Family
int k= 10;
}
if ( oSfntName.language_id == 0x0409 && oSfntName.name_id == 16 && oSfntName.platform_id == 3 )
{
// Preffered family
int k= 10;
}
}
BOOL bFixedWidth = FT_IS_FIXED_WIDTH( pFace );
TT_OS2 *pOs2 = (TT_OS2 *)FT_Get_Sfnt_Table( pFace, ft_sfnt_os2 );
BYTE *pPanose = NULL;
ULONG ulRange1 = 0, ulRange2 = 0, ulRange3 = 0, ulRange4 = 0, ulCodeRange1 = 0, ulCodeRange2 = 0;
USHORT usWidth = 0, usWeight = 0;
SHORT sFamilyClass = 0;
SHORT shAvgCharWidth = 0, shAscent = 0, shDescent = 0, shLineGap = 0, shXHeight = 0, shCapHeight = 0;
if ( NULL != pOs2 )
{
pPanose = (BYTE *)pOs2->panose;
ulRange1 = pOs2->ulUnicodeRange1;
ulRange2 = pOs2->ulUnicodeRange2;
ulRange3 = pOs2->ulUnicodeRange3;
ulRange4 = pOs2->ulUnicodeRange4;
ulCodeRange1 = pOs2->ulCodePageRange1;
ulCodeRange2 = pOs2->ulCodePageRange2;
usWeight = pOs2->usWeightClass;
usWidth = pOs2->usWidthClass;
sFamilyClass = pOs2->sFamilyClass;
if ( 0 != pFace->units_per_EM )
{
double dKoef = ( 1000 / (double)pFace->units_per_EM );
shAvgCharWidth = (SHORT)(pOs2->xAvgCharWidth * dKoef);
shAscent = (SHORT)(pOs2->sTypoAscender * dKoef);
shDescent = (SHORT)(pOs2->sTypoDescender * dKoef);
shLineGap = (SHORT)(pOs2->sTypoLineGap * dKoef);
shXHeight = (SHORT)(pOs2->sxHeight * dKoef);
shCapHeight = (SHORT)(pOs2->sCapHeight * dKoef);
}
else
{
shAvgCharWidth = (SHORT)pOs2->xAvgCharWidth;
shAscent = (SHORT)pOs2->sTypoAscender;
shDescent = (SHORT)pOs2->sTypoDescender;
shLineGap = (SHORT)pOs2->sTypoLineGap;
shXHeight = (SHORT)pOs2->sxHeight;
shCapHeight = (SHORT)pOs2->sCapHeight;
}
}
if ( true )
{
// Ñïåöèàëüíàÿ âåòêà äëÿ ñëó÷àåâ, êîãäà charset ìîæåò áûòü çàäàí íå ÷åðåç çíà÷åíèÿ
// ulCodePageRange, à íåïîñðåäñòâåííî ÷åðåç òèï Cmap.
// Charset Name Charset Value(hex) Codepage number Platform_ID Encoding_ID Description
// -------------------------------------------------------------------------------------------------
//
// SYMBOL_CHARSET 2 (x02) 3 0 Symbol
// SHIFTJIS_CHARSET 128 (x80) 932 3 2 ShiftJIS
// GB2313_CHARSET 134 (x86) 936 3 3 PRC
// CHINESEBIG5_CHARSET 136 (x88) 950 3 4 Big5
// HANGEUL_CHARSET 129 (x81) 949 3 5 Wansung
// JOHAB_CHARSET 130 (x82) 1361 3 6 Johab
for( int nIndex = 0; nIndex < pFace->num_charmaps; nIndex++ )
{
// Symbol
if ( !( ulCodeRange1 & 0x80000000 ) && 0 == pFace->charmaps[nIndex]->encoding_id && 3 == pFace->charmaps[nIndex]->platform_id )
ulCodeRange1 |= 0x80000000;
// ShiftJIS
if ( !( ulCodeRange1 & 0x00020000 ) && 2 == pFace->charmaps[nIndex]->encoding_id && 3 == pFace->charmaps[nIndex]->platform_id )
ulCodeRange1 |= 0x00020000;
// PRC
if ( !( ulCodeRange1 & 0x00040000 ) && 3 == pFace->charmaps[nIndex]->encoding_id && 3 == pFace->charmaps[nIndex]->platform_id )
ulCodeRange1 |= 0x00040000;
// Big5
if ( !( ulCodeRange1 & 0x00100000 ) && 4 == pFace->charmaps[nIndex]->encoding_id && 3 == pFace->charmaps[nIndex]->platform_id )
ulCodeRange1 |= 0x00100000;
// Wansung
if ( !( ulCodeRange1 & 0x00080000 ) && 5 == pFace->charmaps[nIndex]->encoding_id && 3 == pFace->charmaps[nIndex]->platform_id )
ulCodeRange1 |= 0x00080000;
// Johab
if ( !( ulCodeRange1 & 0x00200000 ) && 6 == pFace->charmaps[nIndex]->encoding_id && 3 == pFace->charmaps[nIndex]->platform_id )
ulCodeRange1 |= 0x00200000;
}
}
EFontFormat eFormat = GetFontFormat( pFace );
CWinFontInfo *pWinFontInfo = new CWinFontInfo( CStringW( (char*)pFace->family_name ), CStringW( (char*)pFace->style_name ), wsFilePath.GetBuffer(), nIndex, bBold, bItalic, bFixedWidth, pPanose, ulRange1, ulRange2, ulRange3, ulRange4, ulCodeRange1, ulCodeRange2, usWeight, usWidth, sFamilyClass, eFormat, shAvgCharWidth, shAscent, shDescent, shLineGap, shXHeight, shCapHeight );
Add( pWinFontInfo );
FT_Done_Face( pFace );
}
wsPath[0] = _T('\0');
}
}
CWinFontList(FT_Library pLibrary, CString sDir)
{
m_lDefIndex = -1;
m_pFonts = new CList();
WIN32_FIND_DATA oFD;
CString sSpec = sDir + _T("\\*.*");
HANDLE hRes = FindFirstFile( sSpec, &oFD );
if( INVALID_HANDLE_VALUE == hRes )
return;
do
{
sSpec = oFD.cFileName;
if( sSpec != _T(".") && sSpec != _T("..") )
{
sSpec = sDir + _T("\\") + sSpec;
if( !( oFD.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
{
int nError = 0;
FT_Face pFace = NULL;
CStringW wsFilePath = sSpec;
if ( nError = FT_New_FaceW( pLibrary, wsFilePath.GetBuffer(), 0, &pFace ) )
continue;
// TO DO: Øðèôòû, êîòîðûå íåëüçÿ ñêåéëèòü (ò.å. èçìåíÿòü ðàçìåð
// ïðîèçâîëüíî) ìû íå ãðóçèì. Âîçìîæíî â áóäóùåì íàäî áóäåò
// ñäåëàòü, ÷òîáû ðàáîòàë è òàêîé âàðèàíò. (â Word òàêèå øðèôòû
// íå èñïîëüçóþòñÿ)
if ( !( pFace->face_flags & FT_FACE_FLAG_SCALABLE ) )
{
FT_Done_Face( pFace );
continue;
}
int nFacesCount = pFace->num_faces;
if ( nError = FT_Done_Face( pFace ) )
{
continue;
}
for ( int nIndex = 0; nIndex < nFacesCount; nIndex++ )
{
if ( FT_New_FaceW( pLibrary, wsFilePath.GetBuffer(), nIndex, &pFace ) )
{
continue;
}
BOOL bBold = ( pFace->style_flags & FT_STYLE_FLAG_BOLD ? 1 : 0 );
BOOL bItalic = pFace->style_flags & FT_STYLE_FLAG_ITALIC;
CStringW wsPostscriptName = CStringW( FT_Get_Postscript_Name( pFace ) );
//if ( wsPostscriptName.GetLength() <= 0 )
// CStringW wsPostscriptName = CStringW( (char*)pFace->family_name );
int nNamesCount = FT_Get_Sfnt_Name_Count( pFace );
for ( int nNameIndex = 0; nNameIndex < nNamesCount; nNameIndex++ )
{
FT_SfntName_ oSfntName;
FT_Get_Sfnt_Name( pFace, nNameIndex, &oSfntName );
if ( oSfntName.language_id == 0x0409 && oSfntName.name_id == 1 && oSfntName.platform_id == 3 )
{
// Family
int k= 10;
}
if ( oSfntName.language_id == 0x0409 && oSfntName.name_id == 16 && oSfntName.platform_id == 3 )
{
// Preffered family
int k= 10;
}
}
BOOL bFixedWidth = FT_IS_FIXED_WIDTH( pFace );
TT_OS2 *pOs2 = (TT_OS2 *)FT_Get_Sfnt_Table( pFace, ft_sfnt_os2 );
BYTE *pPanose = NULL;
ULONG ulRange1 = 0, ulRange2 = 0, ulRange3 = 0, ulRange4 = 0, ulCodeRange1 = 0, ulCodeRange2 = 0;
USHORT usWidth = 0, usWeight = 0;
SHORT sFamilyClass = 0;
SHORT shAvgCharWidth = 0, shAscent = 0, shDescent = 0, shLineGap = 0, shXHeight = 0, shCapHeight = 0;
if ( NULL != pOs2 )
{
pPanose = (BYTE *)pOs2->panose;
ulRange1 = pOs2->ulUnicodeRange1;
ulRange2 = pOs2->ulUnicodeRange2;
ulRange3 = pOs2->ulUnicodeRange3;
ulRange4 = pOs2->ulUnicodeRange4;
ulCodeRange1 = pOs2->ulCodePageRange1;
ulCodeRange2 = pOs2->ulCodePageRange2;
usWeight = pOs2->usWeightClass;
usWidth = pOs2->usWidthClass;
sFamilyClass = pOs2->sFamilyClass;
if ( 0 != pFace->units_per_EM )
{
double dKoef = ( 1000 / (double)pFace->units_per_EM );
shAvgCharWidth = (SHORT)(pOs2->xAvgCharWidth * dKoef);
shAscent = (SHORT)(pOs2->sTypoAscender * dKoef);
shDescent = (SHORT)(pOs2->sTypoDescender * dKoef);
shLineGap = (SHORT)(pOs2->sTypoLineGap * dKoef);
shXHeight = (SHORT)(pOs2->sxHeight * dKoef);
shCapHeight = (SHORT)(pOs2->sCapHeight * dKoef);
}
else
{
shAvgCharWidth = (SHORT)pOs2->xAvgCharWidth;
shAscent = (SHORT)pOs2->sTypoAscender;
shDescent = (SHORT)pOs2->sTypoDescender;
shLineGap = (SHORT)pOs2->sTypoLineGap;
shXHeight = (SHORT)pOs2->sxHeight;
shCapHeight = (SHORT)pOs2->sCapHeight;
}
}
if ( true )
{
// Ñïåöèàëüíàÿ âåòêà äëÿ ñëó÷àåâ, êîãäà charset ìîæåò áûòü çàäàí íå ÷åðåç çíà÷åíèÿ
// ulCodePageRange, à íåïîñðåäñòâåííî ÷åðåç òèï Cmap.
// Charset Name Charset Value(hex) Codepage number Platform_ID Encoding_ID Description
// -------------------------------------------------------------------------------------------------
//
// SYMBOL_CHARSET 2 (x02) 3 0 Symbol
// SHIFTJIS_CHARSET 128 (x80) 932 3 2 ShiftJIS
// GB2313_CHARSET 134 (x86) 936 3 3 PRC
// CHINESEBIG5_CHARSET 136 (x88) 950 3 4 Big5
// HANGEUL_CHARSET 129 (x81) 949 3 5 Wansung
// JOHAB_CHARSET 130 (x82) 1361 3 6 Johab
for( int nIndex = 0; nIndex < pFace->num_charmaps; nIndex++ )
{
// Symbol
if ( !( ulCodeRange1 & 0x80000000 ) && 0 == pFace->charmaps[nIndex]->encoding_id && 3 == pFace->charmaps[nIndex]->platform_id )
ulCodeRange1 |= 0x80000000;
// ShiftJIS
if ( !( ulCodeRange1 & 0x00020000 ) && 2 == pFace->charmaps[nIndex]->encoding_id && 3 == pFace->charmaps[nIndex]->platform_id )
ulCodeRange1 |= 0x00020000;
// PRC
if ( !( ulCodeRange1 & 0x00040000 ) && 3 == pFace->charmaps[nIndex]->encoding_id && 3 == pFace->charmaps[nIndex]->platform_id )
ulCodeRange1 |= 0x00040000;
// Big5
if ( !( ulCodeRange1 & 0x00100000 ) && 4 == pFace->charmaps[nIndex]->encoding_id && 3 == pFace->charmaps[nIndex]->platform_id )
ulCodeRange1 |= 0x00100000;
// Wansung
if ( !( ulCodeRange1 & 0x00080000 ) && 5 == pFace->charmaps[nIndex]->encoding_id && 3 == pFace->charmaps[nIndex]->platform_id )
ulCodeRange1 |= 0x00080000;
// Johab
if ( !( ulCodeRange1 & 0x00200000 ) && 6 == pFace->charmaps[nIndex]->encoding_id && 3 == pFace->charmaps[nIndex]->platform_id )
ulCodeRange1 |= 0x00200000;
}
}
EFontFormat eFormat = GetFontFormat( pFace );
CWinFontInfo *pWinFontInfo = new CWinFontInfo( CStringW( (char*)pFace->family_name ), CStringW( (char*)pFace->style_name ), wsFilePath.GetBuffer(), nIndex, bBold, bItalic, bFixedWidth, pPanose, ulRange1, ulRange2, ulRange3, ulRange4, ulCodeRange1, ulCodeRange2, usWeight, usWidth, sFamilyClass, eFormat, shAvgCharWidth, shAscent, shDescent, shLineGap, shXHeight, shCapHeight );
Add( pWinFontInfo );
FT_Done_Face( pFace );
}
}
}
} while( FindNextFile( hRes, &oFD ) );
FindClose( hRes );
}
CWinFontList(CString sWinFontsXml)
{
m_lDefIndex = -1;
m_pFonts = new CList();
XmlUtils::CXmlNode oMainNode;
oMainNode.FromXmlString( sWinFontsXml );
if ( _T("WinFontList") == oMainNode.GetName() )
{
XmlUtils::CXmlNodes oFonts;
oMainNode.GetNodes( _T("WinFontEntry"), oFonts );
for ( int nIndex = 0; nIndex < oFonts.GetCount(); nIndex++ )
{
XmlUtils::CXmlNode oFontNode;
if ( oFonts.GetAt( nIndex, oFontNode ) )
{
CWinFontInfo *pWinFontInfo = CWinFontInfo::FromXml( oFontNode );
if ( NULL != pWinFontInfo )
Add( pWinFontInfo );
}
}
}
}
CWinFontList(BYTE* pBuffer, CString sFontDir)
{
m_lDefIndex = -1;
m_pFonts = new CList();
LONG lCount = *((LONG*)pBuffer);
pBuffer += g_lSizeofLONG;
for (LONG nIndex = 0; nIndex < lCount; ++nIndex)
{
CWinFontInfo *pWinFontInfo = CWinFontInfo::FromBuffer( pBuffer, sFontDir );
Add(pWinFontInfo);
}
}
~CWinFontList()
{
DeleteCList( m_pFonts, CWinFontInfo );
}
CList *GetFonts()
{
return m_pFonts;
}
CWinFontInfo *GetByIndex(int nIndex)
{
return (CWinFontInfo *)m_pFonts->GetByIndex( nIndex );
}
CWinFontInfo *GetByParams(const CString& sParamsXml)
{
if ( m_pFonts->GetLength() <= 0 )
return NULL;
//********************************************
/*
CString sXml = _T("<FontProperties>\
<Name value='Tahoma'/>\
<AltName value='Helvetica'/>\
<Charset value='EE'/>\
<FamilyClass name='swiss'/>\
<Style bold='1' italic='0'/>\
<FixedWidth value='0'/>\
<Panose value='001F2A3B4C5D6F738491'/>\
<UnicodeRange range1='F7FFAFFF' range2='E9DFFFFF' range3='0000003F' range4='00000000' coderange1='003F01FF' coderange2='00000000'/>\
<Weight value='550'/>\
<Width value='1000'/>\
<FontFormat value='1'/>\
<AvgCharWidth value='267'/>\
<Ascent value='850'/>\
<Descent value='-109'/>\
<LineGap value='217'/>\
<xHeight value='745'/>\
<CapHeight value='848'/>\
</FontProperties>");
*/
//********************************************
CString wsFamilyName, wsFamilyClass, wsAltName;
unsigned char unCharset = 0;
BOOL bBold = FALSE, bItalic = FALSE, bFixedWidth = FALSE;
BYTE pPanose[10];
ULONG ulRange1 = 0, ulRange2 = 0, ulRange3 = 0, ulRange4 = 0, ulCodeRange1 = 0, ulCodeRange2 = 0;
USHORT usWeight = 0, usWidth = 0;
SHORT sFamilyClass = 0;
EFontFormat eFontFormat = fontTrueType;
SHORT shAvgCharWidth = 0, shAscent = 0, shDescent = 0, shLineGap = 0, shXHeight = 0, shCapHeight = 0;
BOOL bIsName = FALSE, bIsAltName = FALSE, bIsStyle = FALSE, bIsFixed = FALSE, bIsPanose = FALSE, bIsRanges = FALSE, bIsWeight = FALSE, bIsWidth = FALSE, bIsFamilyClass = FALSE;
BOOL bIsAvgWidth = FALSE, bIsAscent = FALSE, bIsDescent = FALSE, bIsLineGap = FALSE, bIsXHeight = FALSE, bIsCapHeight = FALSE;
// Ñ÷èòûâàåì íàñòðîéêè øðèôòà
XmlUtils::CXmlNode oMainNode;
oMainNode.FromXmlString( sParamsXml );
if ( _T("FontProperties") == oMainNode.GetName() )
{
XmlUtils::CXmlNode oNode;
if ( oMainNode.GetNode( _T("Name"), oNode ) )
{
bIsName = TRUE;
wsFamilyName = oNode.GetAttribute( _T("value") );
}
if ( oMainNode.GetNode( _T("AltName"), oNode ) )
{
bIsAltName = TRUE;
wsAltName = oNode.GetAttribute( _T("value") );
if ( wsAltName.GetLength() <= 0 )
bIsAltName = FALSE;
}
if ( oMainNode.GetNode( _T("Style"), oNode ) )
{
bIsStyle = TRUE;
bBold = (BOOL)XmlUtils::GetInteger( oNode.GetAttribute( _T("bold") ) );
bItalic = (BOOL)XmlUtils::GetInteger( oNode.GetAttribute( _T("italic") ) );
}
if ( oMainNode.GetNode( _T("FixedWidth"), oNode ) )
{
bIsFixed = TRUE;
bFixedWidth = (BOOL)XmlUtils::GetInteger( oNode.GetAttribute( _T("value") ) );
}
if ( oMainNode.GetNode( _T("Panose"), oNode ) )
{
CString sValue = oNode.GetAttribute( _T("value") );
if ( 20 == sValue.GetLength() )
{
for ( int nIndex = 0; nIndex < 10; nIndex++ )
{
int nChar1 = sValue.GetAt( nIndex * 2 );
int nChar2 = sValue.GetAt( nIndex * 2 + 1 );
unsigned char unValue = ((unsigned char)( HexToInt( nChar1 ) << 4 )) | HexToInt( nChar2 );
pPanose[nIndex] = unValue;
// Åñëè õîòü îäíî çíà÷åíèå íå 0, òî èñïîëüçóåì Panose
if ( 0 != unValue )
bIsPanose = TRUE;
}
}
}
if ( oMainNode.GetNode( _T("UnicodeRange"), oNode ) )
{
ulRange1 = (ULONG)HexToInt( oNode.GetAttribute( _T("range1") ) );
ulRange2 = (ULONG)HexToInt( oNode.GetAttribute( _T("range2") ) );
ulRange3 = (ULONG)HexToInt( oNode.GetAttribute( _T("range3") ) );
ulRange4 = (ULONG)HexToInt( oNode.GetAttribute( _T("range4") ) );
ulCodeRange1 = (ULONG)HexToInt( oNode.GetAttribute( _T("coderange1") ) );
ulCodeRange2 = (ULONG)HexToInt( oNode.GetAttribute( _T("coderange2") ) );
if ( !( 0 == ulRange1 && 0 == ulRange2 && 0 == ulRange3 && 0 == ulRange4 && 0 == ulCodeRange1 && 0 == ulCodeRange2 ) )
bIsRanges = TRUE;
}
if ( oMainNode.GetNode( _T("Weight"), oNode ) )
{
usWeight = (USHORT)XmlUtils::GetInteger( oNode.GetAttribute( _T("value") ) );
if ( 0 != usWeight )
bIsWeight = TRUE;
}
if ( oMainNode.GetNode( _T("Width"), oNode ) )
{
bIsWidth = TRUE;
usWidth = (USHORT)XmlUtils::GetInteger( oNode.GetAttribute( _T("value") ) );
}
if ( oMainNode.GetNode( _T("FamilyClass"), oNode ) )
{
bIsFamilyClass = TRUE;
wsFamilyClass = oNode.GetAttribute( _T("type"), _T("") );
sFamilyClass = (SHORT)XmlUtils::GetInteger( oNode.GetAttribute( _T("value") ) );
}
if ( oMainNode.GetNode( _T("FontFormat"), oNode ) )
{
// Ôîðìàò ìû âñåãäà ñðàâíèâàåì
eFontFormat = (EFontFormat)XmlUtils::GetInteger( oNode.GetAttribute( _T("value") ) );
}
if ( oMainNode.GetNode( _T("Charset"), oNode ) )
{
// Åñëè charset íå çàäàí, òî ñ÷èòàåì åãî íóëåâûì (Cp-1252)
unCharset = (unsigned char)HexToInt( oNode.GetAttribute( _T("value") ) );
}
else
unCharset = UNKNOWN_CHARSET;
if ( oMainNode.GetNode( _T("AvgCharWidth"), oNode ) )
{
bIsAvgWidth = TRUE;
shAvgCharWidth = (SHORT)XmlUtils::GetInteger( oNode.GetAttribute( _T("value") ) );
}
if ( oMainNode.GetNode( _T("Ascent"), oNode ) )
{
bIsAscent = TRUE;
shAscent = (SHORT)XmlUtils::GetInteger( oNode.GetAttribute( _T("value") ) );
}
if ( oMainNode.GetNode( _T("Descent"), oNode ) )
{
bIsDescent = TRUE;
shDescent = (SHORT)XmlUtils::GetInteger( oNode.GetAttribute( _T("value") ) );
}
if ( oMainNode.GetNode( _T("LineGap"), oNode ) )
{
bIsLineGap = TRUE;
shLineGap = (SHORT)XmlUtils::GetInteger( oNode.GetAttribute( _T("value") ) );
}
if ( oMainNode.GetNode( _T("xHeight"), oNode ) )
{
bIsXHeight = TRUE;
shXHeight = (SHORT)XmlUtils::GetInteger( oNode.GetAttribute( _T("value") ) );
}
if ( oMainNode.GetNode( _T("CapHeight"), oNode ) )
{
bIsCapHeight = TRUE;
shCapHeight = (SHORT)XmlUtils::GetInteger( oNode.GetAttribute( _T("value") ) );
}
}
bool bIsCorrectFromDict = NSFontDictionary::CorrectParamsFromDictionary(wsFamilyName, bBold, bItalic,
bFixedWidth, pPanose, ulRange1, ulRange2, ulRange3, ulRange4, ulCodeRange1, ulCodeRange2, usWeight, usWidth,
sFamilyClass, shAvgCharWidth, shAscent, shDescent, shLineGap, shXHeight, shCapHeight, bIsStyle,
bIsFixed, bIsPanose, bIsRanges, bIsWeight, bIsWidth, bIsFamilyClass, bIsAvgWidth, bIsAscent, bIsDescent, bIsLineGap, bIsXHeight, bIsCapHeight);
int nMinIndex = 0; // Íîìåð øðèôòà â ñïèñêå ñ ìèíèìàëüíûì âåñîì
int nMinPenalty = 0; // Ìèíèìàëüíûé âåñ
int nDefPenalty = INT_MAX;
for ( int nIndex = 0; nIndex < m_pFonts->GetLength(); nIndex++ )
{
int nCurPenalty = 0;
CWinFontInfo *pInfo = (CWinFontInfo *)m_pFonts->GetByIndex( nIndex );
if ( bIsPanose )
{
nCurPenalty += GetPanosePenalty( pInfo->m_aPanose, pPanose );
}
ULONG arrCandRanges[6] = { pInfo->m_ulUnicodeRange1, pInfo->m_ulUnicodeRange2, pInfo->m_ulUnicodeRange3, pInfo->m_ulUnicodeRange4, pInfo->m_ulCodePageRange1, pInfo->m_ulCodePageRange2 };
if ( bIsRanges && bIsCorrectFromDict )
{
ULONG arrReqRanges[6] = { ulRange1, ulRange2, ulRange3, ulRange4, ulCodeRange1, ulCodeRange2 };
nCurPenalty += GetSigPenalty( arrCandRanges, arrReqRanges, 1000, true );
}
if ( bIsFixed )
nCurPenalty += GetFixedPitchPenalty( pInfo->m_bIsFixed, bFixedWidth );
if ( bIsAltName && bIsName )
{
nCurPenalty += min( GetFaceNamePenalty( pInfo->m_wsFontName, wsFamilyName ), GetFaceNamePenalty( pInfo->m_wsFontName, wsAltName ) );
}
else if ( bIsName )
nCurPenalty += GetFaceNamePenalty( pInfo->m_wsFontName, wsFamilyName );
else if ( bIsAltName )
nCurPenalty += GetFaceNamePenalty( pInfo->m_wsFontName, wsAltName );
if ( bIsWidth )
nCurPenalty += GetWidthPenalty( pInfo->m_usWidth, usWidth );
if ( bIsWeight )
nCurPenalty += GetWeightPenalty( pInfo->m_usWeigth, usWeight );
if ( bIsStyle )
{
nCurPenalty += GetItalicPenalty( pInfo->m_bItalic, bItalic );
nCurPenalty += GetBoldPenalty( pInfo->m_bBold, bBold );
}
if ( bIsFamilyClass )
{
if ( _T("") != wsFamilyClass )
nCurPenalty += GetFamilyUnlikelyPenalty( pInfo->m_sFamilyClass, wsFamilyClass );
else
nCurPenalty += GetFamilyUnlikelyPenalty( pInfo->m_sFamilyClass, sFamilyClass );
}
nCurPenalty += GetFontFormatPenalty( pInfo->m_eFontFormat, eFontFormat );
nCurPenalty += GetCharsetPenalty( arrCandRanges, unCharset );
if ( bIsAvgWidth )
nCurPenalty += GetAvgWidthPenalty( pInfo->m_shAvgCharWidth, shAvgCharWidth );
if ( bIsAscent )
nCurPenalty += GetAscentPenalty( pInfo->m_shAscent, shAscent );
if ( bIsDescent )
nCurPenalty += GetDescentPenalty( pInfo->m_shDescent, shDescent );
if ( bIsLineGap )
nCurPenalty += GetLineGapPenalty( pInfo->m_shLineGap, shLineGap );
if ( bIsXHeight )
nCurPenalty += GetXHeightPenalty( pInfo->m_shXHeight, shXHeight );
if ( bIsCapHeight )
nCurPenalty += GetCapHeightPenalty( pInfo->m_shCapHeight, shCapHeight );
if ( 0 == nIndex )
{
nMinIndex = 0;
nMinPenalty = nCurPenalty;
}
else if ( nCurPenalty < nMinPenalty )
{
nMinIndex = nIndex;
nMinPenalty = nCurPenalty;
}
if ( -1 != m_lDefIndex && nIndex == m_lDefIndex )
{
nDefPenalty = nCurPenalty;
}
// Íàøåëñÿ øðèôò, óäîâëåòâîðÿþùèé âñåì ïàðàìåòðàì, äàëüøå èñêàòü íåò ñìûñëà
if ( 0 == nCurPenalty )
break;
}
if ( -1 != m_lDefIndex && nDefPenalty == nMinPenalty )
nMinIndex = m_lDefIndex;
return (CWinFontInfo *)m_pFonts->GetByIndex( nMinIndex );
}
CWinFontInfo *GetByParams(wchar_t* wsAltFontName, long lCharset, wchar_t* wsFamily, long lStyle, long lFixed, wchar_t *wsPanose, long lUnicodeRange1, long lUnicodeRange2, long lUnicodeRange3, long lUnicodeRange4, long lCodePageRange1, long lCodePageRange2, long lAvgWidth)
{
if ( m_pFonts->GetLength() <= 0 )
return NULL;
CString wsFamilyName, wsFamilyClass;
unsigned char unCharset = 0;
BOOL bBold = FALSE, bItalic = FALSE, bFixedWidth = FALSE;
BYTE pPanose[10];
ULONG ulRange1 = 0, ulRange2 = 0, ulRange3 = 0, ulRange4 = 0, ulCodeRange1 = 0, ulCodeRange2 = 0;
SHORT shAvgCharWidth = 0;
BOOL bIsName = FALSE, bIsStyle = FALSE, bIsFixed = FALSE, bIsPanose = FALSE, bIsRanges = FALSE, bIsFamilyClass = FALSE, bIsAvgWidth = FALSE;
if ( NULL != wsAltFontName )
{
bIsName = TRUE;
wsFamilyName = CString( wsAltFontName );
}
if ( lStyle >= 0 )
{
bIsStyle = TRUE;
bBold = (lStyle & FontConstants::FontStyleBold ? TRUE : FALSE);
bItalic = (lStyle & FontConstants::FontStyleItalic ? TRUE : FALSE);
}
if ( lFixed >= 0 )
{
bIsFixed = TRUE;
bFixedWidth = ( lFixed > 0 ? TRUE : FALSE );
}
if ( NULL != wsPanose )
{
if ( 20 == wcslen( wsPanose ) )
{
for ( int nIndex = 0; nIndex < 10; nIndex++ )
{
int nChar1 = wsPanose[nIndex * 2 ];
int nChar2 = wsPanose[nIndex * 2 + 1 ];
unsigned char unValue = ((unsigned char)( HexToInt( nChar1 ) << 4 )) | HexToInt( nChar2 );
pPanose[nIndex] = unValue;
// Åñëè õîòü îäíî çíà÷åíèå íå 0, òî èñïîëüçóåì Panose
if ( 0 != unValue )
bIsPanose = TRUE;
}
}
}
ulRange1 = (ULONG)lUnicodeRange1;
ulRange2 = (ULONG)lUnicodeRange2;
ulRange3 = (ULONG)lUnicodeRange3;
ulRange4 = (ULONG)lUnicodeRange4;
ulCodeRange1 = (ULONG)lCodePageRange1;
ulCodeRange2 = (ULONG)lCodePageRange2;
if ( !( 0 == ulRange1 && 0 == ulRange2 && 0 == ulRange3 && 0 == ulRange4 && 0 == ulCodeRange1 && 0 == ulCodeRange2 ) )
bIsRanges = TRUE;
if ( NULL != wsFamily )
{
bIsFamilyClass = TRUE;
wsFamilyClass = CString(wsFamily);
}
if ( lCharset >= 0 )
unCharset = (unsigned char)lCharset;
else
unCharset = UNKNOWN_CHARSET;
if ( lAvgWidth >= 0 )
{
bIsAvgWidth = TRUE;
shAvgCharWidth = (SHORT)lAvgWidth;
}
int nMinIndex = 0; // Íîìåð øðèôòà â ñïèñêå ñ ìèíèìàëüíûì âåñîì
int nMinPenalty = 0; // Ìèíèìàëüíûé âåñ
int nDefPenalty = 0;
for ( int nIndex = 0; nIndex < m_pFonts->GetLength(); nIndex++ )
{
int nCurPenalty = 0;
CWinFontInfo *pInfo = (CWinFontInfo *)m_pFonts->GetByIndex( nIndex );
if ( bIsPanose )
{
nCurPenalty += GetPanosePenalty( pInfo->m_aPanose, pPanose );
}
ULONG arrCandRanges[6] = { pInfo->m_ulUnicodeRange1, pInfo->m_ulUnicodeRange2, pInfo->m_ulUnicodeRange3, pInfo->m_ulUnicodeRange4, pInfo->m_ulCodePageRange1, pInfo->m_ulCodePageRange2 };
if ( bIsRanges )
{
ULONG arrReqRanges[6] = { ulRange1, ulRange2, ulRange3, ulRange4, ulCodeRange1, ulCodeRange2 };
nCurPenalty += GetSigPenalty( arrCandRanges, arrReqRanges, 10000 );
}
if ( bIsFixed )
nCurPenalty += GetFixedPitchPenalty( pInfo->m_bIsFixed, bFixedWidth );
if ( bIsName )
nCurPenalty += GetFaceNamePenalty( pInfo->m_wsFontName, wsFamilyName );
if ( bIsStyle )
{
nCurPenalty += GetItalicPenalty( pInfo->m_bItalic, bItalic );
nCurPenalty += GetBoldPenalty( pInfo->m_bBold, bBold );
}
if ( bIsFamilyClass )
nCurPenalty += GetFamilyUnlikelyPenalty( pInfo->m_sFamilyClass, wsFamilyClass );
nCurPenalty += GetCharsetPenalty( arrCandRanges, unCharset );
if ( bIsAvgWidth )
nCurPenalty += GetAvgWidthPenalty( pInfo->m_shAvgCharWidth, shAvgCharWidth );
if ( 0 == nIndex )
{
nMinIndex = 0;
nMinPenalty = nCurPenalty;
}
else if ( nCurPenalty < nMinPenalty )
{
nMinIndex = nIndex;
nMinPenalty = nCurPenalty;
}
if ( -1 != m_lDefIndex && nIndex == m_lDefIndex )
{
nDefPenalty = nCurPenalty;
}
// Íàøåëñÿ øðèôò, óäîâëåòâîðÿþùèé âñåì ïàðàìåòðàì, äàëüøå èñêàòü íåò ñìûñëà
if ( 0 == nCurPenalty )
break;
}
if ( -1 != m_lDefIndex && nDefPenalty == nMinPenalty )
nMinIndex = m_lDefIndex;
return (CWinFontInfo *)m_pFonts->GetByIndex( nMinIndex );
}
void SetDefaultFont(long lIndex)
{
if ( lIndex >= 0 && lIndex < m_pFonts->GetLength() )
m_lDefIndex = lIndex;
}
static CString GetWinFontsXml(FT_Library pLibrary)
{
XmlUtils::CXmlWriter oWriter;
oWriter.WriteNodeBegin( _T("WinFontList") );
// Èùåì äèðåêòîðèþ ñ ôîíòàìè (îáû÷íî ýòî C:\Windows\Fonts)
wchar_t wsWinFontDir[MAX_PATH];
wsWinFontDir[0] = '\0';
if ( !SHGetSpecialFolderPathW( NULL, wsWinFontDir, CSIDL_FONTS, FALSE ) )
wsWinFontDir[0] = '\0';
OSVERSIONINFO oVersion;
oVersion.dwOSVersionInfoSize = sizeof(oVersion);
GetVersionEx( &oVersion );
wchar_t wsPath[1000];
if ( oVersion.dwPlatformId == VER_PLATFORM_WIN32_NT )
_tcscpy_s( wsPath, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts\\") );
else
_tcscpy_s( wsPath, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts\\") );
TCHAR szName[2 * MAX_PATH];
TCHAR szData[2 * MAX_PATH];
while ( GetNextNameValue( HKEY_LOCAL_MACHINE, wsPath, szName, szData ) == ERROR_SUCCESS)
{
int nError = 0;
FT_Face pFace = NULL;
CStringW wsFilePath( szData );
if ( nError = FT_New_FaceW( pLibrary, wsFilePath.GetBuffer(), 0, &pFace ) )
{
wsFilePath = CStringW( wsWinFontDir ) + CStringW( _T("\\") ) + CStringW( szData );
wsFilePath.Replace( _T("\0"), _T("") );
if ( nError = FT_New_FaceW( pLibrary, wsFilePath.GetBuffer(), 0, &pFace ) )
{
wsPath[0] = _T('\0');
continue;
}
}
// TO DO: Øðèôòû, êîòîðûå íåëüçÿ ñêåéëèòü (ò.å. èçìåíÿòü ðàçìåð
// ïðîèçâîëüíî) ìû íå ãðóçèì. Âîçìîæíî â áóäóùåì íàäî áóäåò
// ñäåëàòü, ÷òîáû ðàáîòàë è òàêîé âàðèàíò. (â Word òàêèå øðèôòû
// íå èñïîëüçóþòñÿ)
if ( !( pFace->face_flags & FT_FACE_FLAG_SCALABLE ) )
{
FT_Done_Face( pFace );
wsPath[0] = _T('\0');
continue;
}
int nFacesCount = pFace->num_faces;
if ( nError = FT_Done_Face( pFace ) )
{
wsPath[0] = _T('\0');
continue;
}
for ( int nIndex = 0; nIndex < nFacesCount; nIndex++ )
{
if ( FT_New_FaceW( pLibrary, wsFilePath.GetBuffer(), nIndex, &pFace ) )
{
wsPath[0] = _T('\0');
continue;
}
BOOL bBold = ( pFace->style_flags & FT_STYLE_FLAG_BOLD ? 1 : 0 );
BOOL bItalic = pFace->style_flags & FT_STYLE_FLAG_ITALIC;
CStringW wsPostscriptName = CStringW( FT_Get_Postscript_Name( pFace ) );
//if ( wsPostscriptName.GetLength() <= 0 )
// CStringW wsPostscriptName = CStringW( (char*)pFace->family_name );
int nNamesCount = FT_Get_Sfnt_Name_Count( pFace );
for ( int nNameIndex = 0; nNameIndex < nNamesCount; nNameIndex++ )
{
FT_SfntName_ oSfntName;
FT_Get_Sfnt_Name( pFace, nNameIndex, &oSfntName );
if ( oSfntName.language_id == 0x0409 && oSfntName.name_id == 1 && oSfntName.platform_id == 3 )
{
// Family
int k= 10;
}
if ( oSfntName.language_id == 0x0409 && oSfntName.name_id == 16 && oSfntName.platform_id == 3 )
{
// Preffered family
int k= 10;
}
}
BOOL bFixedWidth = FT_IS_FIXED_WIDTH( pFace );
TT_OS2 *pOs2 = (TT_OS2 *)FT_Get_Sfnt_Table( pFace, ft_sfnt_os2 );
BYTE *pPanose = NULL;
ULONG ulRange1 = 0, ulRange2 = 0, ulRange3 = 0, ulRange4 = 0, ulCodeRange1 = 0, ulCodeRange2 = 0;
USHORT usWidth = 0, usWeight = 0;
SHORT sFamilyClass = 0;
SHORT shAvgCharWidth = 0, shAscent = 0, shDescent = 0, shLineGap = 0, shXHeight = 0, shCapHeight = 0;
if ( NULL != pOs2 )
{
pPanose = (BYTE *)pOs2->panose;
ulRange1 = pOs2->ulUnicodeRange1;
ulRange2 = pOs2->ulUnicodeRange2;
ulRange3 = pOs2->ulUnicodeRange3;
ulRange4 = pOs2->ulUnicodeRange4;
ulCodeRange1 = pOs2->ulCodePageRange1;
ulCodeRange2 = pOs2->ulCodePageRange2;
usWeight = pOs2->usWeightClass;
usWidth = pOs2->usWidthClass;
sFamilyClass = pOs2->sFamilyClass;
if ( 0 != pFace->units_per_EM )
{
double dKoef = ( 1000 / (double)pFace->units_per_EM );
shAvgCharWidth = (SHORT)(pOs2->xAvgCharWidth * dKoef);
shAscent = (SHORT)(pOs2->sTypoAscender * dKoef);
shDescent = (SHORT)(pOs2->sTypoDescender * dKoef);
shLineGap = (SHORT)(pOs2->sTypoLineGap * dKoef);
shXHeight = (SHORT)(pOs2->sxHeight * dKoef);
shCapHeight = (SHORT)(pOs2->sCapHeight * dKoef);
}
else
{
shAvgCharWidth = (SHORT)pOs2->xAvgCharWidth;
shAscent = (SHORT)pOs2->sTypoAscender;
shDescent = (SHORT)pOs2->sTypoDescender;
shLineGap = (SHORT)pOs2->sTypoLineGap;
shXHeight = (SHORT)pOs2->sxHeight;
shCapHeight = (SHORT)pOs2->sCapHeight;
}
}
EFontFormat eFormat = GetFontFormat( pFace );
CWinFontInfo oWinFontInfo( CStringW( (char*)pFace->family_name ), CStringW( (char*)pFace->style_name ), wsFilePath.GetBuffer(), nIndex, bBold, bItalic, bFixedWidth, pPanose, ulRange1, ulRange2, ulRange3, ulRange4, ulCodeRange1, ulCodeRange2, usWeight, usWidth, sFamilyClass, eFormat, shAvgCharWidth, shAscent, shDescent, shLineGap, shXHeight, shCapHeight );
oWinFontInfo.WriteToXml( &oWriter );
FT_Done_Face( pFace );
}
wsPath[0] = _T('\0');
}
oWriter.WriteNodeEnd( _T("WinFontList") );
return oWriter.GetXmlString();
}
static BYTE* GetWinFontsData(FT_Library pLibrary, LONG& lDataSize)
{
// Èùåì äèðåêòîðèþ ñ ôîíòàìè (îáû÷íî ýòî C:\Windows\Fonts)
wchar_t wsWinFontDir[MAX_PATH];
CAtlArray<CWinFontInfo*> arrInfos;
wsWinFontDir[0] = '\0';
if ( !SHGetSpecialFolderPathW( NULL, wsWinFontDir, CSIDL_FONTS, FALSE ) )
wsWinFontDir[0] = '\0';
OSVERSIONINFO oVersion;
oVersion.dwOSVersionInfoSize = sizeof(oVersion);
GetVersionEx( &oVersion );
wchar_t wsPath[1000];
if ( oVersion.dwPlatformId == VER_PLATFORM_WIN32_NT )
_tcscpy_s( wsPath, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts\\") );
else
_tcscpy_s( wsPath, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts\\") );
TCHAR szName[2 * MAX_PATH];
TCHAR szData[2 * MAX_PATH];
while ( GetNextNameValue( HKEY_LOCAL_MACHINE, wsPath, szName, szData ) == ERROR_SUCCESS)
{
int nError = 0;
FT_Face pFace = NULL;
CStringW wsFilePath( szData );
if ( nError = FT_New_FaceW( pLibrary, wsFilePath.GetBuffer(), 0, &pFace ) )
{
wsFilePath = CStringW( wsWinFontDir ) + CStringW( _T("\\") ) + CStringW( szData );
wsFilePath.Replace( _T("\0"), _T("") );
if ( nError = FT_New_FaceW( pLibrary, wsFilePath.GetBuffer(), 0, &pFace ) )
{
wsPath[0] = _T('\0');
continue;
}
}
// TO DO: Øðèôòû, êîòîðûå íåëüçÿ ñêåéëèòü (ò.å. èçìåíÿòü ðàçìåð
// ïðîèçâîëüíî) ìû íå ãðóçèì. Âîçìîæíî â áóäóùåì íàäî áóäåò
// ñäåëàòü, ÷òîáû ðàáîòàë è òàêîé âàðèàíò. (â Word òàêèå øðèôòû
// íå èñïîëüçóþòñÿ)
if ( !( pFace->face_flags & FT_FACE_FLAG_SCALABLE ) )
{
FT_Done_Face( pFace );
wsPath[0] = _T('\0');
continue;
}
int nFacesCount = pFace->num_faces;
if ( nError = FT_Done_Face( pFace ) )
{
wsPath[0] = _T('\0');
continue;
}
for ( int nIndex = 0; nIndex < nFacesCount; nIndex++ )
{
if ( FT_New_FaceW( pLibrary, wsFilePath.GetBuffer(), nIndex, &pFace ) )
{
wsPath[0] = _T('\0');
continue;
}
BOOL bBold = ( pFace->style_flags & FT_STYLE_FLAG_BOLD ? 1 : 0 );
BOOL bItalic = pFace->style_flags & FT_STYLE_FLAG_ITALIC;
CStringW wsPostscriptName = CStringW( FT_Get_Postscript_Name( pFace ) );
//if ( wsPostscriptName.GetLength() <= 0 )
// CStringW wsPostscriptName = CStringW( (char*)pFace->family_name );
int nNamesCount = FT_Get_Sfnt_Name_Count( pFace );
for ( int nNameIndex = 0; nNameIndex < nNamesCount; nNameIndex++ )
{
FT_SfntName_ oSfntName;
FT_Get_Sfnt_Name( pFace, nNameIndex, &oSfntName );
if ( oSfntName.language_id == 0x0409 && oSfntName.name_id == 1 && oSfntName.platform_id == 3 )
{
// Family
int k= 10;
}
if ( oSfntName.language_id == 0x0409 && oSfntName.name_id == 16 && oSfntName.platform_id == 3 )
{
// Preffered family
int k= 10;
}
}
BOOL bFixedWidth = FT_IS_FIXED_WIDTH( pFace );
TT_OS2 *pOs2 = (TT_OS2 *)FT_Get_Sfnt_Table( pFace, ft_sfnt_os2 );
BYTE *pPanose = NULL;
ULONG ulRange1 = 0, ulRange2 = 0, ulRange3 = 0, ulRange4 = 0, ulCodeRange1 = 0, ulCodeRange2 = 0;
USHORT usWidth = 0, usWeight = 0;
SHORT sFamilyClass = 0;
SHORT shAvgCharWidth = 0, shAscent = 0, shDescent = 0, shLineGap = 0, shXHeight = 0, shCapHeight = 0;
if ( NULL != pOs2 )
{
pPanose = (BYTE *)pOs2->panose;
ulRange1 = pOs2->ulUnicodeRange1;
ulRange2 = pOs2->ulUnicodeRange2;
ulRange3 = pOs2->ulUnicodeRange3;
ulRange4 = pOs2->ulUnicodeRange4;
ulCodeRange1 = pOs2->ulCodePageRange1;
ulCodeRange2 = pOs2->ulCodePageRange2;
usWeight = pOs2->usWeightClass;
usWidth = pOs2->usWidthClass;
sFamilyClass = pOs2->sFamilyClass;
if ( 0 != pFace->units_per_EM )
{
double dKoef = ( 1000 / (double)pFace->units_per_EM );
shAvgCharWidth = (SHORT)(pOs2->xAvgCharWidth * dKoef);
shAscent = (SHORT)(pOs2->sTypoAscender * dKoef);
shDescent = (SHORT)(pOs2->sTypoDescender * dKoef);
shLineGap = (SHORT)(pOs2->sTypoLineGap * dKoef);
shXHeight = (SHORT)(pOs2->sxHeight * dKoef);
shCapHeight = (SHORT)(pOs2->sCapHeight * dKoef);
}
else
{
shAvgCharWidth = (SHORT)pOs2->xAvgCharWidth;
shAscent = (SHORT)pOs2->sTypoAscender;
shDescent = (SHORT)pOs2->sTypoDescender;
shLineGap = (SHORT)pOs2->sTypoLineGap;
shXHeight = (SHORT)pOs2->sxHeight;
shCapHeight = (SHORT)pOs2->sCapHeight;
}
}
EFontFormat eFormat = GetFontFormat( pFace );
CWinFontInfo* __pInfo = new CWinFontInfo( CStringW( (char*)pFace->family_name ), CStringW( (char*)pFace->style_name ), wsFilePath.GetBuffer(), nIndex, bBold, bItalic, bFixedWidth, pPanose, ulRange1, ulRange2, ulRange3, ulRange4, ulCodeRange1, ulCodeRange2, usWeight, usWidth, sFamilyClass, eFormat, shAvgCharWidth, shAscent, shDescent, shLineGap, shXHeight, shCapHeight );
arrInfos.Add(__pInfo);
FT_Done_Face( pFace );
}
wsPath[0] = _T('\0');
}
lDataSize = g_lSizeofLONG;
for (size_t i = 0; i < arrInfos.GetCount(); ++i)
{
lDataSize += arrInfos[i]->GetBufferLen();
}
BYTE* pData = new BYTE[lDataSize];
BYTE* pDataMem = pData;
*(LONG*)pDataMem = (LONG)arrInfos.GetCount();
pDataMem += g_lSizeofLONG;
for (size_t i = 0; i < arrInfos.GetCount(); ++i)
{
CWinFontInfo* pInfo = arrInfos[i];
pInfo->ToBuffer(pDataMem);
RELEASEOBJECT(pInfo);
}
arrInfos.RemoveAll();
return pData;
}
void ToBuffer(BYTE** pDstData, LONG* pLen, CString strDirectory = _T(""))
{
LONG lDataSize = g_lSizeofLONG;
size_t nCountFonts = m_pFonts->GetLength();
for (size_t i = 0; i < nCountFonts; ++i)
{
lDataSize += ((CWinFontInfo*)(m_pFonts->GetByIndex((int)i)))->GetBufferLen(strDirectory);
}
BYTE* pData = new BYTE[lDataSize];
BYTE* pDataMem = pData;
*(LONG*)pDataMem = (LONG)nCountFonts;
pDataMem += g_lSizeofLONG;
for (size_t i = 0; i < nCountFonts; ++i)
{
CWinFontInfo* pInfo = ((CWinFontInfo*)(m_pFonts->GetByIndex((int)i)));
pInfo->ToBuffer(pDataMem, strDirectory);
}
*pDstData = pData;
*pLen = lDataSize;
}
static EFontFormat GetFontFormat(FT_Face pFace)
{
CString wsFormat( FT_Get_X11_Font_Format( pFace ) );
if ( _T("Windows FNT") == wsFormat )
return fontWindowsFNT;
else if ( _T("TrueType") == wsFormat )
return fontTrueType;
else if ( _T("CFF") == wsFormat )
return fontOpenType;
return fontUnknown;
}
private:
void Add(CWinFontInfo *pFontInfo)
{
for ( int nIndex = 0; nIndex < m_pFonts->GetLength(); ++nIndex )
{
if ( ((CWinFontInfo *)m_pFonts->GetByIndex(nIndex))->Equals( pFontInfo ) )
{
if ( pFontInfo )
delete pFontInfo;
return;
}
}
m_pFonts->Append( pFontInfo );
}
unsigned char HexToInt(int nHex)
{
if ( nHex >= '0' && nHex <= '9' ) return (unsigned char)(nHex - '0');
if ( nHex >= 'a' && nHex <= 'f' ) return (unsigned char)(nHex - 'a' + 10);
if ( nHex >= 'A' && nHex <= 'F' ) return (unsigned char)(nHex - 'A' + 10);
return 0;
}
__int64 HexToInt(CString sHex)
{
__int64 nResult = 0;
__int64 nMult = 1;
for ( int nIndex = sHex.GetLength() - 1; nIndex >= 0; nIndex-- )
{
nResult += HexToInt( sHex.GetAt( nIndex ) ) * nMult;
nMult <<= 4;
}
return nResult;
}
int GetCharsetPenalty(ULONG ulCandRanges[6], unsigned char unReqCharset)
{
// Penalty = 65000 (ýòî ñàìûé âåñîìûé ïàðàìåòð)
if ( UNKNOWN_CHARSET == unReqCharset )
return 0;
unsigned long ulBit = 0;
unsigned int unLongIndex = 0;
GetCodePageByCharset( unReqCharset, &ulBit, &unLongIndex );
int nMult = 1;
for ( int nIndex = 0; nIndex < (int)ulBit; nIndex++ )
nMult <<= 1;
if ( !(ulCandRanges[unLongIndex] & nMult) )
return 65000;
return 0;
}
int GetSigPenalty(ULONG ulCandRanges[6], ULONG ulReqRanges[6], double dRangeWeight = 1, bool bPenaltyForSuperflouous = false)
{
double dPenalty = 0;
// Äëÿ íà÷àëà ïðîñìàòðèâàåì ñêîëüêî âîîáùå ðàçëè÷íûõ ïðîñòðàíñòâ íàäî.
// Èñõîäÿ èç èõ îáùåãî êîëè÷åñòâà, íàõîäèì âåñ 1 ïðîïóùåíîãî ïðîñòðàíñòâà.
unsigned char arrCandidate[192], arrRequest[192];
memset( arrCandidate, 0x00, 192 );
memset( arrRequest, 0x00, 192 );
int nRangesCount = 0; // Êîëè÷åñòâî íåîáõîäèìûõ ïðîñòðàíñòâ
int nAddCount = 0; // êîëè÷åñòâî äîïîëíèòåëüíûõ(íåíóæíûõ) ïðîñòðàíñòâ ó êàíäèäàòà
for ( int nIndex = 0; nIndex < 6; nIndex++ )
{
for ( unsigned long nBitCount = 0, nBit = 1; nBitCount < 32; nBitCount++, nBit *= 2 )
{
BOOL bReqAdd = FALSE;
if ( ulReqRanges[nIndex] & nBit )
{
arrRequest[ nIndex * 32 + nBitCount ] = 1;
nRangesCount++;
bReqAdd = TRUE;
}
if ( ulCandRanges[nIndex] & nBit )
{
arrCandidate[ nIndex * 32 + nBitCount ] = 1;
if ( !bReqAdd )
nAddCount++;
}
}
}
if ( 0 == nRangesCount )
return 0;
//double dRangeWeight = 1;//1000.0 / nRangesCount;
for ( int nIndex = 0; nIndex < 192; nIndex++ )
{
if ( 1 == arrRequest[nIndex] && 0 == arrCandidate[nIndex] )
dPenalty += dRangeWeight;
else if ( bPenaltyForSuperflouous && 0 == arrRequest[nIndex] && 1 == arrCandidate[nIndex] )
dPenalty += dRangeWeight;
}
return (int)dPenalty;
}
int GetFixedPitchPenalty(BOOL bCandFixed, BOOL bReqFixed)
{
int nPenalty = 0;
// Åñëè çàïðàøèâàåòñÿ ìîíîøèðèííûé, à êàíäèäàò íå ìîíîøèðèííûé, òî âåñ 15000
// Åñëè çàïðàøèâàåòñÿ íå ìîíîøèðèííûé, à êàíäèäàò ìîíîøèðèííûé, òî âåñ 350
if ( bReqFixed && !bCandFixed )
nPenalty = 15000;
if ( !bReqFixed && bCandFixed )
nPenalty = 350;
return nPenalty;
}
int GetFaceNamePenalty(CString sCandName, CString sReqName)
{
// Íà MSDN íàïèñàíî, ÷òî åñëè èìåíà íå ñîâïàäàþò, òî âåñ 10000.
// Ìû áóäåì ñðàâíèâàòü ñêîëüêî ñîâïàëî ñèìâîëîâ ó çàïðàøèâàåìîãî
// èìåíè è ñ èìåíåì êàíäèäàòà, áåç ó÷åòà ðåøèñòðà, ïðîáåëîâ, çàïÿòûõ
// è òèðå.
sCandName.Remove(' '); sReqName.Remove(' ');
sCandName.Remove(','); sReqName.Remove(',');
sCandName.Remove('-'); sReqName.Remove('-');
sCandName.MakeLower(); sReqName.MakeLower();
if ( 0 == sReqName.GetLength() )
return 0;
if ( 0 == sCandName.GetLength() )
return 10000;
if ( sReqName == sCandName )
return 0;
else if ( -1 != sReqName.Find( sCandName ) || -1 != sCandName.Find( sReqName ) )
return 1000;
return 10000;
}
int GetFamilyUnlikelyPenalty(SHORT nCandFamilyClass, SHORT nReqFamilyClass)
{
// Requested a roman/modern/swiss family, but the candidate is
// decorative/script. Or requested decorative/script, and the
// candidate is roman/modern/swiss. Penalty = 50.
int nReqClassID = nReqFamilyClass >> 8;
int nCandClassID = nCandFamilyClass >> 8;
if ( 0 == nReqClassID ) // Unknown
return 0;
if ( 0 == nCandClassID ) // Unknown
return 50;
if ( ( nReqClassID <= 8 && nCandClassID > 8 ) || ( nReqClassID > 8 && nCandClassID <= 8 ) )
return 50;
return 0;
}
int GetFamilyUnlikelyPenalty(int nCandFamilyClass, CString sReqFamilyClass)
{
// Requested a roman/modern/swiss family, but the candidate is
// decorative/script. Or requested decorative/script, and the
// candidate is roman/modern/swiss. Penalty = 50.
int nCandClassID = nCandFamilyClass >> 8;
sReqFamilyClass.MakeLower();
if ( _T("any") == sReqFamilyClass || _T("unknown") == sReqFamilyClass )
return 0;
else if ( 0 == nCandClassID )
return 50;
else if ( ( ( _T("swiss") == sReqFamilyClass || _T("roman") == sReqFamilyClass || _T("modern") == sReqFamilyClass ) && nCandClassID > 8 ) || ( ( _T("decorative") == sReqFamilyClass || _T("script") == sReqFamilyClass ) && nCandClassID <= 8 ) )
return 50;
return 0;
}
int GetWidthPenalty(USHORT usCandWidth, USHORT usReqWidth)
{
// Penalty * width difference (Penalty = 50)
return abs( (int)usCandWidth - (int)usReqWidth ) * 50;
}
int GetWeightPenalty(USHORT usCandWeight, USHORT usReqWeight)
{
// Penalty * ( weight difference / 10 ) (Penalty = 3)
return (3 * ( abs( (int)usCandWeight - (int)usReqWeight ) / 10 ));
}
int GetItalicPenalty(BOOL bCandItalic, BOOL bReqItalic)
{
// Penalty = 4
if ( bCandItalic != bReqItalic )
return 4;
return 0;
}
int GetBoldPenalty(BOOL bCandBold, BOOL bReqBold)
{
// SmallPenalty
// Penalty = 1
if ( bCandBold != bReqBold )
return 1;
return 0;
}
int GetFontFormatPenalty(EFontFormat eCandFormat, EFontFormat eReqFormat)
{
// Âîîáùå, íà ÌSDN íàïèñàíî òîëüêî ïðî TrueType. Íî ìû áóäåì ñðàâíèâàòü
// âñå òèïû ôîðìàòîâ è ïðè íåñîâïàäåíèè äàåì âåñ = 4. Åñëè ôîðìàò íå çàäàí
// òî ïî óìîë÷àíèþ ñ÷èòàåì åãî TrueType.
if ( eReqFormat == fontUnknown )
{
// Ñ÷èòàåì, ÷òî êîãäà ôîðìàò íå èçâåñòåí, çíà÷èò ýòî 100% íå TrueType.
if ( eCandFormat == fontTrueType )
return 4;
else
return 0;
}
if ( eCandFormat != eReqFormat )
return 4;
return 0;
}
int GetPanosePenalty(BYTE *pCandPanose, BYTE *pReqPanose)
{
int nPenalty = 0;
for ( int nIndex = 0; nIndex < 10; nIndex++ )
{
if ( pCandPanose[nIndex] != pReqPanose[nIndex] && 0 != pReqPanose[nIndex] )
{
int nKoef = abs(pCandPanose[nIndex] - pReqPanose[nIndex]);
switch(nIndex)
{
case 0: nPenalty += 1000 * nKoef; break;
case 1: nPenalty += 100 * nKoef; break;
case 2: nPenalty += 100 * nKoef; break;
case 3: nPenalty += 100 * nKoef; break;
case 4: nPenalty += 100 * nKoef; break;
case 5: nPenalty += 100 * nKoef; break;
case 6: nPenalty += 100 * nKoef; break;
case 7: nPenalty += 100 * nKoef; break;
case 8: nPenalty += 100 * nKoef; break;
case 9: nPenalty += 100 * nKoef; break;
}
}
}
return nPenalty;
}
int GetAvgWidthPenalty(SHORT shCandWidth, SHORT shReqWidth)
{
if ( 0 == shCandWidth && 0 != shReqWidth )
return 4000;
return abs( shCandWidth - shReqWidth ) * 4;
}
int GetAscentPenalty(SHORT shCandAscent, SHORT shReqAscent)
{
if ( 0 == shCandAscent && 0 != shReqAscent )
return 100;
return abs( shCandAscent - shReqAscent ) / 10;
}
int GetDescentPenalty(SHORT shCandDescent, SHORT shReqDescent)
{
if ( 0 == shCandDescent && 0 != shReqDescent )
return 100;
return abs( shCandDescent - shReqDescent ) / 10;
}
int GetLineGapPenalty(SHORT shCandLineGap, SHORT shReqLineGap)
{
if ( 0 == shCandLineGap && 0 != shReqLineGap )
return 100;
return abs( shCandLineGap - shReqLineGap ) / 10;
}
int GetXHeightPenalty(SHORT shCandXHeight, SHORT shReqXHeight)
{
if ( 0 == shCandXHeight && 0 != shReqXHeight )
return 50;
return abs( shCandXHeight - shReqXHeight ) / 20;
}
int GetCapHeightPenalty(SHORT shCandCapHeight, SHORT shReqCapHeight)
{
if ( 0 == shCandCapHeight && 0 != shReqCapHeight )
return 50;
return abs( shCandCapHeight - shReqCapHeight ) / 20;
}
public:
CString GetAllStylesByFontName(const CString& strName)
{
CString strAllStyles = _T("<styles>");
int nCount = m_pFonts->GetLength();
for (int i = 0; i < nCount; ++i)
{
CWinFontInfo* pInfo = GetByIndex(i);
if (pInfo->m_wsFontName == strName)
{
LONG lStyle = 0;
if (pInfo->m_bBold)
lStyle |= 1;
if (pInfo->m_bItalic)
lStyle |= 2;
CString strPath = pInfo->m_wsFontPath;
strPath.Replace(_T("'"), _T("&apos;"));
strPath.Replace(_T("<"), _T("&lt;"));
strPath.Replace(_T(">"), _T("&gt;"));
strPath.Replace(_T("\""), _T("&quot;"));
strPath.Replace(_T("&"), _T("&amp;"));
CString s = _T("");
s.Format(_T("<font style=\"%d\" path=\"%s\" faceindex=\"%d\"/>"), lStyle, strPath, pInfo->m_lIndex);
strAllStyles += s;
}
}
strAllStyles += _T("</styles>");
return strAllStyles;
}
private:
CList *m_pFonts; // [CWinFontInfo]
wchar_t m_wsWinFontDir[MAX_PATH]; //
long m_lDefIndex; // Íîìåð ñòàíäàðòíîãî øðèôòà (-1, åñëè íå çàäàí)
};
#endif /* _WIN_FONT */