#ifndef _WIN_FONT_H #define _WIN_FONT_H #include #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("'"), _T("'")); strText.Replace(_T("<"), _T("<")); strText.Replace(_T(">"), _T(">")); strText.Replace(_T("""), _T("\"")); strText.Replace(_T("&"), _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("\ \ \ \ \