diff options
Diffstat (limited to 'FontInfo.cpp')
-rw-r--r-- | FontInfo.cpp | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/FontInfo.cpp b/FontInfo.cpp new file mode 100644 index 0000000..beed324 --- /dev/null +++ b/FontInfo.cpp @@ -0,0 +1,325 @@ +// FontInfo.cpp : Implementation of CFontInfo +#include "stdafx.h" +#include "TtfInfo.h" +#include "FontInfo.h" + +///////////////////////////////////////////////////////////////////////////// +// CFontInfo +LPCTSTR CFontInfo::m_strFontsKey = NULL; + +STDMETHODIMP CFontInfo::InterfaceSupportsErrorInfo(REFIID riid) +{ + static const IID* arr[] = + { + &IID_ITrueTypeFontInfo, + }; + for ( int i = 0; i < sizeof( arr ) / sizeof( arr[0] ); i++ ) + { + if ( InlineIsEqualGUID( *arr[i], riid ) ) + return S_OK; + } + return S_FALSE; +} + +STDMETHODIMP CFontInfo::get__FileName(BSTR * pVal) +{ + *pVal = m_bstrFileName.copy(); + return S_OK; +} + +STDMETHODIMP CFontInfo::put__FileName(BSTR newVal) +{ + using namespace std; + + Initialize(); + + try + { + m_bstrFileName = _bstr_t(newVal).copy(); + } + catch (_com_error Err) + { + m_bstrFileName = ""; + return Err.Error(); + } + + const int BUFFER_SIZE = 512; + const int MAX_TABLES = 40; + + wchar_t namebuf[BUFFER_SIZE]; + unsigned short numNames; + unsigned int cTables; + sfnt_OffsetTable OffsetTable; + sfnt_DirectoryEntry Table; + sfnt_NamingTable NamingTable; + sfnt_NameRecord NameRecord; + streampos curseek; + + try + { + + USES_CONVERSION; + ifstream TtfFile( W2CA( newVal ), ios_base::in | ios_base::binary ); + + if ( !TtfFile.is_open() ) + { + m_bstrFileName = ""; + return AtlReportError( CLSID_FontInfo, IDERR_FileOpen, GUID_NULL, E_FAIL, _Module.GetResourceInstance() ); + } + + TtfFile.read( reinterpret_cast<char*>( &OffsetTable ), sizeof( OffsetTable ) - sizeof( sfnt_DirectoryEntry ) ); + cTables = (int) SWAPW( OffsetTable.numOffsets ); + + for (int i = 0; i < cTables and i < MAX_TABLES; i++) + { + TtfFile.read( reinterpret_cast<char*>( &Table ), sizeof( Table ) ); + + if (Table.tag == tag_NamingTable) + { + TtfFile.seekg( SWAPL( Table.offset ) ); + TtfFile.read( reinterpret_cast<char*>( &NamingTable ), + sizeof( NamingTable ) ); + numNames = SWAPW( NamingTable.count ); + + while ( numNames-- ) + { + TtfFile.read ( reinterpret_cast<char*>( &NameRecord ), + sizeof( NameRecord ) ); + + curseek = TtfFile.tellg(); + + if ( SWAPW( NameRecord.platformID ) == TTF::Microsoft ) + { + TtfFile.seekg( SWAPW( NameRecord.offset ) + + SWAPW( NamingTable.stringOffset ) + + SWAPL( Table.offset ) ); + TtfFile.read( reinterpret_cast<char*>( &namebuf ), + min(SWAPW(NameRecord.length), BUFFER_SIZE) ); + namebuf[SWAPW( NameRecord.length ) / sizeof( wchar_t ) ] = L'\0'; + + for (int i = 0; i < BUFFER_SIZE and i < SWAPW( NameRecord.length ) / sizeof( wchar_t ); i++) + namebuf[i] = SWAPW( namebuf[i] ); + + TtfFile.seekg( curseek ); + + switch ( SWAPW( NameRecord.nameID ) ) + { + case TTF::Copyright: + m_bstrCopyright = namebuf; + break; + case TTF::Family: + m_bstrFamily = namebuf; + break; + case TTF::ID: + m_bstrID = namebuf; + break; + case TTF::Name: + m_bstrName = namebuf; + break; + case TTF::PostscriptName: + m_bstrPostscriptName = namebuf; + break; + case TTF::Subfamily: + m_bstrSubfamily = namebuf; + break; + case TTF::Trademark: + m_bstrTrademark = namebuf; + break; + case TTF::Version: + m_bstrVersion = namebuf; + break; + default: + break; + } + + } // if ( SWAPW( NameRecord.platformID ) == TTF::Microsoft + + } // while ( numNames-- ) + + } // if (Table.tag == tag_NamingTable) + + } // for (int i = 0; i < cTables and i < 40; i++) + + } + catch(...) + { + return E_UNEXPECTED; + } + + return S_OK; +} + +STDMETHODIMP CFontInfo::get_FileName(BSTR * pVal) +{ + return get__FileName(pVal); +} + +STDMETHODIMP CFontInfo::put_FileName(BSTR newVal) +{ + return put__FileName(newVal); +} + +STDMETHODIMP CFontInfo::get_Copyright(BSTR * pVal) +{ + *pVal = m_bstrCopyright.copy(); + return S_OK; +} + +STDMETHODIMP CFontInfo::get_Family(BSTR * pVal) +{ + *pVal = m_bstrFamily.copy(); + return S_OK; +} + +STDMETHODIMP CFontInfo::get_ID(BSTR * pVal) +{ + *pVal = m_bstrID.copy(); + return S_OK; +} + +STDMETHODIMP CFontInfo::get_Name(BSTR * pVal) +{ + *pVal = m_bstrName.copy(); + return S_OK; +} + +STDMETHODIMP CFontInfo::get_PostscriptName(BSTR * pVal) +{ + *pVal = m_bstrPostscriptName.copy(); + return S_OK; +} + +STDMETHODIMP CFontInfo::get_Subfamily(BSTR * pVal) +{ + *pVal = m_bstrSubfamily.copy(); + return S_OK; +} + +STDMETHODIMP CFontInfo::get_Trademark(BSTR * pVal) +{ + *pVal = m_bstrTrademark.copy(); + return S_OK; +} + +STDMETHODIMP CFontInfo::get_Version(BSTR * pVal) +{ + *pVal = m_bstrVersion.copy(); + return S_OK; +} + +STDMETHODIMP CFontInfo::get_RegisteredFileName(BSTR * pVal) +{ + CRegKey reg; + LONG lRet = 0; + + lRet = OpenFontsKey( reg, KEY_READ ); + // We'll only return an error in the event that we can't open + // the Fonts key, any other registry errors will result in an + // empty RegisteredFileName string + if ( ERROR_SUCCESS != lRet ) + return HRESULT_FROM_WIN32( lRet ); + + // First get the size + DWORD dwSize = 0; + lRet = reg.QueryValue( NULL, GetRegistryFontName(), &dwSize ); + + if ( 0 == dwSize ) + { + *pVal = _bstr_t("").copy(); + return S_OK; + } + + LPTSTR strFileName = new TCHAR [dwSize]; + lRet = reg.QueryValue( strFileName, GetRegistryFontName(), &dwSize ); + + if ( ERROR_SUCCESS != lRet) + *pVal = _bstr_t("").copy(); + else + *pVal = _bstr_t(strFileName).copy(); + + delete [] strFileName; + return S_OK; +} + +STDMETHODIMP CFontInfo::GetFontsDirectory(BSTR * pVal) +{ + LPITEMIDLIST pIDL = NULL; + HRESULT hRes = SHGetSpecialFolderLocation( NULL, CSIDL_FONTS, &pIDL ); + + if ( SUCCEEDED( hRes ) ) + { + TCHAR pszPath [MAX_PATH] = {0}; + BOOL bSuccess = SHGetPathFromIDList( pIDL, pszPath ); + CoTaskMemFree( pIDL ); + if ( bSuccess ) + { + *pVal = _bstr_t( pszPath ).copy(); + return S_OK; + } + else + hRes = E_FAIL; + } + + return AtlReportError( CLSID_FontInfo, IDERR_GetFontsDirectory, GUID_NULL, hRes, _Module.GetResourceInstance() ); +} + +STDMETHODIMP CFontInfo::Install(VARIANT_BOOL bPermanent) +{ + if ( _bstr_t("") == m_bstrFileName ) + return AtlReportError( CLSID_FontInfo, + IDERR_NoFileName, GUID_NULL, E_FAIL, _Module.GetResourceInstance() ); + + if ( VARIANT_TRUE == bPermanent ) + { + // It's up to the user to check whether this font is already installed + CRegKey reg; + LONG lRet = 0; + + lRet = OpenFontsKey( reg, KEY_WRITE ); + if ( ERROR_SUCCESS != lRet ) + return AtlReportError( CLSID_FontInfo, + IDERR_OpenFontsKey, GUID_NULL, HRESULT_FROM_WIN32( lRet ), _Module.GetResourceInstance() ); + + lRet = reg.SetValue( m_bstrFileName, GetRegistryFontName() ); + if ( ERROR_SUCCESS != lRet ) + return AtlReportError( CLSID_FontInfo, + IDERR_Install, GUID_NULL, HRESULT_FROM_WIN32( lRet ), _Module.GetResourceInstance() ); + + } + + int ret = AddFontResource( m_bstrFileName ); + ::SendMessage( HWND_BROADCAST, WM_FONTCHANGE, 0, 0 ); + + return S_OK; +} + +STDMETHODIMP CFontInfo::Uninstall(VARIANT_BOOL bPermanent) +{ + if ( _bstr_t("") == m_bstrFileName ) + return AtlReportError( CLSID_FontInfo, + IDERR_NoFileName, GUID_NULL, E_FAIL, _Module.GetResourceInstance() ); + + if ( VARIANT_TRUE == bPermanent ) + { + // It's up to the user to ensure that they really + // want to remove the font before calling this method + CRegKey reg; + LONG lRet = 0; + + lRet = OpenFontsKey(reg, KEY_WRITE ); + if ( ERROR_SUCCESS != lRet ) + return AtlReportError( CLSID_FontInfo, + IDERR_OpenFontsKey, GUID_NULL, HRESULT_FROM_WIN32( lRet ), _Module.GetResourceInstance() ); + + lRet = reg.DeleteValue( GetRegistryFontName() ); + if ( ERROR_SUCCESS != lRet ) + return AtlReportError( CLSID_FontInfo, + IDERR_Uninstall, GUID_NULL, HRESULT_FROM_WIN32( lRet ), _Module.GetResourceInstance() ); + + } + + int ret = RemoveFontResource( m_bstrFileName ); + ::SendMessage( HWND_BROADCAST, WM_FONTCHANGE, 0, 0 ); + + return S_OK; +} |