summaryrefslogtreecommitdiff
path: root/FontInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'FontInfo.cpp')
-rw-r--r--FontInfo.cpp325
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;
+}