home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / Chapt_14 / FontEmbed / FontEmbed.cpp next >
Encoding:
C/C++ Source or Header  |  2000-05-12  |  11.5 KB  |  502 lines

  1. //-----------------------------------------------------------------------------------//
  2. //              Windows Graphics Programming: Win32 GDI and DirectDraw               //
  3. //                             ISBN  0-13-086985-6                                   //
  4. //                                                                                   //
  5. //  Written            by  Yuan, Feng                             www.fengyuan.com   //
  6. //  Copyright (c) 2000 by  Hewlett-Packard Company                www.hp.com         //
  7. //  Published          by  Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com      //
  8. //                                                                                   //
  9. //  FileName   : fontembed.cpp                                                         //
  10. //  Description: Font embedding demo program, Chapter 14                             //
  11. //  Version    : 1.00.000, May 31, 2000                                              //
  12. //-----------------------------------------------------------------------------------//
  13.  
  14. #define STRICT
  15. #define _WIN32_WINNT 0x0500
  16.  
  17. #include <windows.h>
  18. #include <tchar.h>
  19. #include <string.h>
  20. #include <assert.h>
  21.  
  22. #include "resource.h"
  23. #include "..\..\include\Dialog.h"
  24.  
  25.  
  26. #define FR_HIDDEN   0x01
  27. #define FR_MEM        0x02
  28.  
  29.  
  30. BOOL RemoveFont(const TCHAR * fontname, int option, HANDLE hFont)
  31. {
  32.     if ( option & FR_MEM )
  33.     {
  34.         return RemoveFontMemResourceEx(hFont);
  35.     }
  36.     
  37.     TCHAR ttffile[MAX_PATH];
  38.     TCHAR fotfile[MAX_PATH];
  39.  
  40.     GetCurrentDirectory(MAX_PATH-1, ttffile);
  41.     _tcscpy(fotfile, ttffile);
  42.  
  43.     wsprintf(ttffile + _tcslen(ttffile), "\\%s.ttf", fontname);
  44.     wsprintf(fotfile + _tcslen(fotfile), "\\%s.fot", fontname);
  45.  
  46.     BOOL rslt;
  47.  
  48.     switch ( option )
  49.     {
  50.         case 0:
  51.         case FR_HIDDEN:
  52.             rslt = RemoveFontResource(fotfile);
  53.             break;
  54.  
  55.         case FR_PRIVATE:
  56.         case FR_NOT_ENUM:
  57.         case FR_PRIVATE | FR_NOT_ENUM:
  58.             rslt = RemoveFontResourceEx(fotfile, option, NULL);
  59.             break;
  60.  
  61.         default:
  62.             assert(false);
  63.             rslt = FALSE;
  64.     }
  65.  
  66.     if ( ! DeleteFile(fotfile) )
  67.         rslt = FALSE;
  68.  
  69.     if ( ! DeleteFile(ttffile) )
  70.         rslt = FALSE;
  71.  
  72.     return rslt;
  73. }
  74.  
  75.  
  76. HANDLE InstallFont(void * fontdata, unsigned fontsize, const TCHAR * fontname, int option)
  77. {
  78.     if ( option & FR_MEM )
  79.     {
  80.         DWORD num;
  81.  
  82.         return AddFontMemResourceEx(fontdata, fontsize, NULL, & num);
  83.     }
  84.  
  85.     TCHAR ttffile[MAX_PATH];
  86.     TCHAR fotfile[MAX_PATH];
  87.  
  88.     GetCurrentDirectory(MAX_PATH-1, ttffile);
  89.     _tcscpy(fotfile, ttffile);
  90.  
  91.     wsprintf(ttffile + _tcslen(ttffile), "\\%s.ttf", fontname);
  92.     wsprintf(fotfile + _tcslen(fotfile), "\\%s.fot", fontname);
  93.  
  94.     HANDLE hFile = CreateFile(ttffile, GENERIC_WRITE, 0, NULL,
  95.                         CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0);
  96.  
  97.     if ( hFile==INVALID_HANDLE_VALUE )
  98.         return NULL;
  99.  
  100.     DWORD dwWritten;
  101.     WriteFile(hFile, fontdata, fontsize, & dwWritten, NULL);
  102.     FlushFileBuffers(hFile);
  103.     CloseHandle(hFile);
  104.  
  105.     if ( ! CreateScalableFontResource(option & FR_HIDDEN, fotfile, ttffile, NULL) )
  106.         return NULL;
  107.  
  108.     switch ( option )
  109.     {
  110.         case 0:
  111.         case FR_HIDDEN:
  112.             return (HANDLE) AddFontResource(fotfile);
  113.  
  114.         case FR_PRIVATE:
  115.         case FR_NOT_ENUM:
  116.         case FR_PRIVATE | FR_NOT_ENUM:
  117.             return (HANDLE) AddFontResourceEx(fotfile, option, NULL);
  118.  
  119.         default:
  120.             assert(false);
  121.             return NULL;
  122.     }
  123. }
  124.  
  125. const char key[4] = { 0x31, 0x41, 0x59, 0x26 }; // encryption key, pi
  126.  
  127. typedef struct
  128. {
  129.     char    Tag[4];            // font
  130.     DWORD    size;            // size of attached font data
  131.     char    FileName[56];
  132. }    FontEmbed;
  133.  
  134.  
  135. // Load/unload a document, install/uninstall the fonts embedded inside
  136.  
  137. int ProcessDocument(const TCHAR * docname, int option, bool load, HANDLE hfont[])
  138. {
  139.     HANDLE handle = CreateFile(docname, GENERIC_READ, FILE_SHARE_READ, 
  140.         NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  141.     
  142.     if ( handle == INVALID_HANDLE_VALUE )
  143.         return 0;
  144.  
  145.     int       processed  = 0;
  146.     DWORD      dwRead;
  147.     FontEmbed header;
  148.  
  149.     while ( ReadFile(handle, & header, sizeof(header), & dwRead, NULL) )
  150.     {
  151.         if ( dwRead!=sizeof(header) )
  152.             break;
  153.  
  154.         if ( strncmp(header.Tag, "FONT", 4) )
  155.             break;
  156.  
  157.         unsigned size = header.size - sizeof(header);
  158.  
  159.         BYTE * pData = new BYTE[size];
  160.  
  161.         if ( pData==NULL )
  162.             break;
  163.  
  164.         ReadFile(handle, pData, size, & dwRead, NULL);
  165.  
  166.         // simple decryption
  167.         for (unsigned i=0; i<size; i++)
  168.             pData[i] ^= key[i % 4];
  169.  
  170.         if ( load )
  171.             hfont[processed] = InstallFont(pData, size, header.FileName, option);
  172.         else
  173.             if ( ! RemoveFont(header.FileName, option, hfont[processed]) )
  174.             {
  175.                 delete [] pData;
  176.                 break;
  177.             }
  178.         
  179.         delete [] pData;
  180.  
  181.         if ( hfont[processed] )
  182.             processed ++;
  183.         else
  184.             break;
  185.     }
  186.  
  187.     CloseHandle(handle);
  188.  
  189.     return processed;
  190. }
  191.  
  192. class KFileDialog
  193. {
  194.     void SetupOFN(OPENFILENAME & ofn, TCHAR Filter[], HWND hWnd, const TCHAR * pExtension, const TCHAR * pClass);
  195.  
  196. public:
  197.     TCHAR    m_FileName[MAX_PATH];
  198.     TCHAR    m_TitleName[MAX_PATH];
  199.     
  200.     // "bmp" "Bitmap Files"
  201.     BOOL GetOpenFileName(HWND hWnd, const TCHAR * pExtension, const TCHAR * pClass);
  202.     BOOL GetSaveFileName(HWND hWnd, const TCHAR * pExtension, const TCHAR * pClass);
  203. };
  204.  
  205.  
  206. void KFileDialog::SetupOFN(OPENFILENAME & ofn, TCHAR Filter[], HWND hWnd, const TCHAR * pExtension, const TCHAR * pClass)
  207. {
  208.     memset(& ofn, 0, sizeof(ofn));
  209.  
  210.     wsprintf(Filter, "%s (*.%s)%c*.%s%c", pClass, pExtension, 0, pExtension, 0);
  211.  
  212.     ofn.lStructSize        = sizeof(OPENFILENAME);
  213.     ofn.hwndOwner        = hWnd;
  214.     ofn.lpstrFilter        = Filter; // _T("Bitmaps (*.bmp)\0*.bmp\0\0");
  215.     ofn.lpstrFile        = m_FileName;
  216.     ofn.nMaxFile        = MAX_PATH;
  217.     ofn.lpstrFileTitle    = m_TitleName;
  218.     ofn.nMaxFileTitle    = MAX_PATH;
  219.     ofn.lpstrDefExt        = pExtension; // _T("bmp");
  220.     ofn.nFilterIndex    = 1;
  221.  
  222.     m_FileName[0] = 0;
  223. }
  224.  
  225.  
  226. BOOL KFileDialog::GetOpenFileName(HWND hWnd, const TCHAR * pExtension, const TCHAR * pClass)
  227. {
  228.     OPENFILENAME ofn;
  229.     TCHAR Filter[MAX_PATH];
  230.  
  231.     SetupOFN(ofn, Filter, hWnd, pExtension, pClass);
  232.  
  233.     ofn.Flags    = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
  234.             
  235.     return ::GetOpenFileName(&ofn);
  236. }
  237.  
  238.  
  239. BOOL KFileDialog::GetSaveFileName(HWND hWnd, const TCHAR * pExtension, const TCHAR * pClass)
  240. {
  241.     OPENFILENAME ofn;
  242.     TCHAR Filter[MAX_PATH];
  243.  
  244.     SetupOFN(ofn, Filter, hWnd, pExtension, pClass);
  245.  
  246.     ofn.Flags  = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
  247.     
  248.     return ::GetSaveFileName(&ofn);
  249. }
  250.  
  251. // Generate a EMF file with fonts embedded as GDI commands
  252.  
  253.  
  254. BOOL GenerateDoc(const TCHAR * docname)
  255. {
  256.     HANDLE out = CreateFile(docname, GENERIC_WRITE, FILE_SHARE_READ, 
  257.         NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  258.  
  259.     if ( out==INVALID_HANDLE_VALUE )
  260.         return FALSE;
  261.  
  262.     KFileDialog fi;
  263.  
  264.     while ( fi.GetOpenFileName(NULL, "ttf", "TrueType fonts") )
  265.     {
  266.         HANDLE handle = CreateFile(fi.m_TitleName, GENERIC_READ, FILE_SHARE_READ, 
  267.             NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  268.     
  269.         if ( handle == INVALID_HANDLE_VALUE )
  270.             break;
  271.  
  272.         DWORD size = GetFileSize(handle, NULL);
  273.  
  274.         FontEmbed font;
  275.         
  276.         memset(&font, 0, sizeof(font));
  277.         font.Tag[0] = 'F';
  278.         font.Tag[1] = 'O';
  279.         font.Tag[2] = 'N';
  280.         font.Tag[3] = 'T';
  281.         font.size   = sizeof(FontEmbed) + size;
  282.  
  283.         int len = strlen(fi.m_TitleName);
  284.  
  285.         for (int i=0; i<len; i++)
  286.             if ( fi.m_TitleName[i]=='.')
  287.                 break;
  288.             else
  289.                 font.FileName[i] = fi.m_TitleName[i];
  290.         
  291.         DWORD dwWritten, dwRead;
  292.  
  293.         // write header
  294.         WriteFile(out, & font, sizeof(font), & dwWritten, NULL);
  295.  
  296.         char buffer[4096];
  297.  
  298.         // read, write the whole font file
  299.         while ( ReadFile(handle, buffer, sizeof(buffer), & dwRead, NULL) )
  300.         {
  301.             if ( dwRead==0) 
  302.                 break;
  303.  
  304.             // simple encryption
  305.             for (unsigned i=0; i<dwRead; i++)
  306.                 buffer[i] ^= key[i % 4];
  307.  
  308.             WriteFile(out, buffer, dwRead, & dwWritten, NULL);
  309.         }
  310.  
  311.         CloseHandle(handle);
  312.     }
  313.  
  314.     CloseHandle(out);
  315.  
  316.     return TRUE;
  317. }
  318.  
  319. const TCHAR * FontList[] =
  320. {
  321.     "Euro Sign",
  322.     "Ozzie Black",
  323.     "Ozzie Black Italic",
  324.     NULL
  325. };
  326.  
  327.  
  328. class KMyDialog : public KDialog
  329. {
  330.     HINSTANCE m_hInst;
  331.     int          m_nFontChange;
  332.     HFONT      m_font[10];
  333.     int          m_option;
  334.  
  335.     void GetOption(void)
  336.     {            
  337.         m_option = 0;
  338.  
  339.         if ( SendDlgItemMessage(m_hWnd, IDC_HIDDEN, BM_GETCHECK, 0, 0)==BST_CHECKED )
  340.             m_option = FR_HIDDEN;
  341.  
  342.         if ( SendDlgItemMessage(m_hWnd, IDC_PRIVATE, BM_GETCHECK, 0, 0)==BST_CHECKED )
  343.             m_option = FR_PRIVATE;
  344.  
  345.         if ( SendDlgItemMessage(m_hWnd, IDC_NOENUM, BM_GETCHECK, 0, 0)==BST_CHECKED )
  346.             m_option = FR_NOT_ENUM;
  347.  
  348.         if ( SendDlgItemMessage(m_hWnd, IDC_MEM, BM_GETCHECK, 0, 0)==BST_CHECKED )
  349.             m_option = FR_MEM;
  350.     }
  351.  
  352.     void Update(void)
  353.     {
  354.         for (int i=0; FontList[i]; i++)
  355.         {
  356.             if ( m_font[i] )
  357.                 DeleteObject(m_font[i]);
  358.  
  359.             LOGFONT logfont = { - 20,
  360.                              0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, 
  361.                              ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, 
  362.                              PROOF_QUALITY, VARIABLE_PITCH };
  363.             
  364.             _tcscpy(logfont.lfFaceName, FontList[i]);
  365.  
  366.             if (i==2) 
  367.                 logfont.lfItalic = TRUE;
  368.  
  369.             if (i==0)
  370.                 logfont.lfCharSet = SYMBOL_CHARSET;
  371.  
  372.             m_font[i] = CreateFontIndirect(& logfont);
  373.  
  374.             HDC      hDC = GetDC(NULL);
  375.             HGDIOBJ hOld = SelectObject(hDC, m_font[i]);
  376.  
  377.             OUTLINETEXTMETRIC outm[3];
  378.             GetOutlineTextMetrics(hDC, sizeof(outm), outm);
  379.             SelectObject(hDC, hOld);
  380.             DeleteObject(hDC);
  381.  
  382.             TCHAR name[64];
  383.             
  384.             if ( i==0 )
  385.                 _tcscpy(name, "e");
  386.             else
  387.             {
  388.                 _tcscpy(name, (char *) outm + (int) outm[0].otmpFamilyName);
  389.                 _tcscat(name, " ");
  390.                 _tcscat(name, (char *) outm + (int) outm[0].otmpStyleName);
  391.             }
  392.  
  393.             SetDlgItemText(m_hWnd, IDC_SAMPLE1 + i, name);
  394.  
  395.             SendDlgItemMessage(m_hWnd, IDC_SAMPLE1 + i, WM_SETFONT, (WPARAM) m_font[i], TRUE);
  396.         }
  397.     }
  398.  
  399.     virtual BOOL OnInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
  400.     {
  401.         m_hWnd = hWnd;
  402.  
  403.         Update();
  404.  
  405.         return TRUE;
  406.     }
  407.  
  408.     HANDLE hFont[32];
  409.  
  410.     virtual BOOL OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
  411.     {
  412.         switch ( LOWORD(wParam) )
  413.         {
  414.             case IDOK:
  415.                 EndDialog(hWnd, IDOK);
  416.                 return TRUE;
  417.  
  418.             case IDC_GENERATE:
  419.                 GenerateDoc("testdoc.tmp");
  420.                 return TRUE;
  421.  
  422.             case IDC_LOAD:
  423.             {
  424.                 GetOption();
  425.                 int succeeded = ProcessDocument("testdoc.tmp", m_option, true, hFont);
  426.  
  427.                 TCHAR mess[32];
  428.                 wsprintf(mess, "%d font(s) installed.", succeeded);
  429.                 MessageBox(NULL, mess, "Font Install", MB_OK);
  430.  
  431.                 if ( succeeded )
  432.                     if ( m_option==0 )
  433.                         SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
  434.                     else
  435.                         Update();
  436.             }
  437.                 return TRUE;
  438.  
  439.             case IDC_UNLOAD:
  440.             {
  441.                 GetOption();
  442.                 int succeeded = ProcessDocument("testdoc.tmp", m_option, false, hFont);
  443.  
  444.                 TCHAR mess[32];
  445.                 wsprintf(mess, "%d font(s) uninstalled.", succeeded);
  446.                 MessageBox(NULL, mess, "Font Install", MB_OK);
  447.  
  448.                 if ( succeeded )
  449.                     if ( m_option==0 )
  450.                         SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
  451.                     else
  452.                         Update();
  453.             }
  454.                 return TRUE;
  455.         }
  456.  
  457.         return FALSE;
  458.     }
  459.  
  460.     virtual BOOL DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  461.     {
  462.         switch (uMsg)
  463.         {
  464.             case WM_INITDIALOG:
  465.                 return OnInitDialog(hWnd, wParam, lParam);
  466.  
  467.             case WM_COMMAND:
  468.                 return OnCommand(hWnd, wParam, lParam);
  469.  
  470.             case WM_FONTCHANGE:
  471.                 {
  472.                     TCHAR mess[32];
  473.  
  474.                     wsprintf(mess, "WM_FONTCHANGE %d", ++m_nFontChange);
  475.                     SetDlgItemText(hWnd, IDC_MESSAGE, mess);
  476.  
  477.                     Update();
  478.                 }
  479.                 return TRUE;
  480.         }
  481.  
  482.         return FALSE;
  483.     }
  484.  
  485. public:
  486.     KMyDialog(HINSTANCE hInst)
  487.     {
  488.         m_hInst       = hInst;
  489.         m_nFontChange = 0;
  490.         m_option      = 0;
  491.  
  492.         memset(m_font, 0, sizeof(m_font));
  493.     }
  494. };
  495.  
  496.  
  497. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
  498. {
  499.     KMyDialog dialog(hInstance);
  500.  
  501.     return dialog.Dialogbox(hInstance, MAKEINTRESOURCE(IDD_FONT));
  502. }