home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / Chapt_15 / Text / Panose.cpp < prev    next >
C/C++ Source or Header  |  2000-05-24  |  11KB  |  503 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   : panose.cpp                                                             //
  10. //  Description: Panose font matching                                                //
  11. //  Version    : 1.00.000, May 31, 2000                                              //
  12. //-----------------------------------------------------------------------------------//
  13.  
  14. #define INITGUID
  15. #define _WIN32_WINNT 0x0500
  16. #define STRICT
  17.  
  18. #pragma pack(push, 4)
  19. #include <windows.h>
  20. #pragma pack(pop)
  21.  
  22. #include <tchar.h>
  23. #include <assert.h>
  24.  
  25. #include "..\..\include\win.h"
  26. #include "..\..\include\canvas.h"
  27. #include "..\..\include\listview.h"
  28. #include "..\..\include\OutlineMetric.h"
  29.  
  30. #include "resource.h"
  31.  
  32. #include "PanMap.h"
  33. #include "Panose.h"
  34.  
  35.  
  36. class KFontMapper
  37. {
  38.     IPANOSEMapper    * m_pMapper;
  39.     const PANOSE    * m_pFontList;
  40.     int                  m_nFontNo;
  41.  
  42. public:
  43.     KFontMapper(void)
  44.     {
  45.         m_pMapper   = NULL;
  46.         m_pFontList = NULL;
  47.         m_nFontNo   = 0;
  48.  
  49.         CoInitialize(NULL);
  50.         CoCreateInstance(CLSID_PANOSEMapper, NULL, CLSCTX_INPROC_SERVER, IID_IPANOSEMapper, 
  51.             (void **) & m_pMapper);
  52.     }
  53.  
  54.     void SetFontList(const PANOSE * pFontList, int nFontNo)
  55.     {
  56.         m_pFontList = pFontList;
  57.         m_nFontNo   = nFontNo;
  58.     }
  59.  
  60.     int PickFonts(const PANOSE * pTarget, unsigned short * pOrder, unsigned short * pScore, int nResult)
  61.     {
  62.         m_pMapper->vPANRelaxThreshold();
  63.  
  64.         int rslt = m_pMapper->unPANPickFonts(
  65.                         pOrder,                    // recieves order of fonts, best-to-worst
  66.                         pScore,                    // receives match result for each font
  67.                         (BYTE *) pTarget,        // the PANOSE number we're mapping to
  68.                         nResult,                // the number of fonts to return
  69.                         (BYTE *) m_pFontList,    // the first font's PANOSE number
  70.                         m_nFontNo,                // the number of fonts to compare
  71.                         sizeof(PANOSE),            // count of bytes between PANOSE numbers
  72.                         pTarget->bFamilyType);    // the PANOSE 'family' to map to
  73.  
  74.         m_pMapper->bPANRestoreThreshold();
  75.  
  76.         return rslt;
  77.     }
  78.     
  79.     ~KFontMapper()
  80.     {
  81.         if ( m_pMapper )
  82.             m_pMapper->Release();
  83.         
  84.         CoUninitialize();
  85.     }
  86. };
  87.  
  88. // 'Arial Bold Italic' -> PANOSE
  89. bool GetPANOSE(HDC hDC, const TCHAR * fullname, PANOSE * panose, TCHAR facename[])
  90. {
  91.     TCHAR name[MAX_PATH];
  92.  
  93.     // remove space before
  94.     while (fullname[0]==' ')
  95.         fullname ++;
  96.  
  97.     _tcscpy(name, fullname);
  98.  
  99.     // remove space after
  100.     for (int i=_tcslen(name)-1; (i>=0) && (name[i]==' '); i--)
  101.         name[i] = 0;
  102.  
  103.     LOGFONT lf;
  104.     memset(&lf, 0, sizeof(lf));
  105.     lf.lfHeight  = 100;
  106.     lf.lfCharSet = DEFAULT_CHARSET;
  107.     lf.lfWeight  = FW_REGULAR;
  108.  
  109.     if ( strstr(name, "Italic") )
  110.         lf.lfItalic = TRUE;
  111.  
  112.     if ( strstr(name, "Bold") )
  113.         lf.lfWeight = FW_BOLD;
  114.  
  115.     _tcscpy(lf.lfFaceName, name);
  116.     
  117.     HFONT hFont = CreateFontIndirect(& lf);
  118.  
  119.     if ( hFont==NULL )
  120.         return false;
  121.  
  122.     HGDIOBJ hOld = SelectObject(hDC, hFont);
  123.  
  124.     {
  125.         KOutlineTextMetric otm(hDC);
  126.     
  127.         if ( otm.GetName(otm.m_pOtm->otmpFaceName) )
  128.         {
  129.             _tcscpy(facename, otm.GetName(otm.m_pOtm->otmpFaceName) ); 
  130.     
  131.             * panose = otm.m_pOtm->otmPanoseNumber;
  132.         }
  133.         else
  134.             facename[0] = 0;
  135.     }
  136.  
  137.     SelectObject(hDC, hOld);
  138.     DeleteObject(hFont);
  139.  
  140.     return facename[0] != 0;
  141. }
  142.  
  143.  
  144. const TCHAR * PAN_FAMILY[] = 
  145. {
  146.     "Any",
  147.     "No Fit",
  148.     "Text and Display",
  149.     "Script",
  150.     "Decorative",
  151.     "Pictorial"
  152. };
  153.  
  154. const TCHAR * PAN_SERIF[] = 
  155. {
  156.     "Any",
  157.     "No Fit",
  158.     "Cove",
  159.     "Obtuse Cove",
  160.     "Square Cove",
  161.     "Obtuse Square Cove",
  162.     "Square",
  163.     "Thin",
  164.     "Bone",
  165.     "Exaggerated",
  166.     "Triangle",
  167.     "Normal Sans",
  168.     "Obtuse Sans",
  169.     "Prep Sans",
  170.     "Flared",
  171.     "Rounded"
  172. };
  173.  
  174. const TCHAR * PAN_WEIGHT[] =
  175. {
  176.     "Any",
  177.     "No Fit",
  178.     "Very Light",
  179.     "Light",
  180.     "Thin",
  181.     "Book",
  182.     "Medium",
  183.     "Demi",
  184.     "Bold",
  185.     "Heavy",
  186.     "Black",
  187.     "Nord"
  188. };
  189.  
  190. const TCHAR * PAN_PROP[] =
  191. {
  192.     "Any",
  193.     "Not Fit",
  194.     "Old Style",
  195.     "Modern",
  196.     "Even Width",
  197.     "Expanded",
  198.     "Condensed",
  199.     "Very Expanded",
  200.     "Very Condensed",
  201.     "Monospaced"
  202. };
  203.  
  204. const TCHAR * PAN_CONTRAST[] =
  205. {
  206.     "Any",
  207.     "Not Fit",
  208.     "None",
  209.     "Very Low",
  210.     "Low",
  211.     "Medium Low",
  212.     "Medium",
  213.     "Mediim High",
  214.     "High",
  215.     "Very High"
  216. };
  217.  
  218. const TCHAR * PAN_STROKE [] =
  219. {
  220.     "Any",
  221.     "Not Fit",
  222.     "Gradual/Diagonal",
  223.     "Gradual/Transitional",
  224.     "Gradual/Vertical",
  225.     "Gradual/Horizontal",
  226.     "Rapid/Vertical",
  227.     "Rapid/Horizontal",
  228.     "Instant/Vertical"
  229. };
  230.  
  231. const TCHAR * PAN_ARM [] =
  232. {
  233.     "Any",
  234.     "Not Fit",
  235.     "Straight Arms/Horizontal",
  236.     "Straight Arms/Wedge",
  237.     "Straight Arms/Vertical",
  238.     "Straight Arms/Single-Serif",
  239.     "Straight Arms/Double-Serif",
  240.     "Non-Straight Arms/Horizontal",
  241.     "Non-Straight Arms/Wedge",
  242.     "Non-Straight Arms/Vertical",
  243.     "Non-Straight Arms/Single-Serif",
  244.     "Non-Straight Arms/Double-Serif"
  245. };
  246.  
  247. const TCHAR * PAN_LETT [] =
  248. {
  249.     "Any",
  250.     "Not Fit",
  251.     "Normal/Contact",
  252.     "Normal/Weighted",
  253.     "Normal/Boxed",
  254.     "Normal/Flattened",
  255.     "Normal/Rounded",
  256.     "Normal/Off Center",
  257.     "Normal/Square",
  258.     "Oblique/Contact",
  259.     "Oblique/Weighted",
  260.     "Oblique/Boxed",
  261.     "Oblique/Flattened",
  262.     "Oblique/Rounded",
  263.     "Oblique/Off Center",
  264.     "Oblique/Square"
  265. };
  266.  
  267. const TCHAR * PAN_MIDLINE [] =
  268. {
  269.     "Any",
  270.     "Not Fit",
  271.     "Standard/Trimmed",
  272.     "Standard/Pointed",
  273.     "Standard/Serifed",
  274.     "High/Trimmed",
  275.     "High/Pointed",
  276.     "High/Serifed",
  277.     "Constant/Trimmed",
  278.     "Constant/Pointed",
  279.     "Constant/Serifed",
  280.     "Low/Trimmed",
  281.     "Low/Pointed",
  282.     "Low/Serifed"
  283. };
  284.  
  285. const TCHAR * PAN_XHEIGHT [] = 
  286. {
  287.     "Any",
  288.     "Not Fit",
  289.     "Constant/Small",
  290.     "Constant/Standard",
  291.     "Constant/Large",
  292.     "Ducking/Small",
  293.     "Ducking/Standard",
  294.     "Ducking/Large"
  295. };
  296.  
  297.  
  298. void KPanoseView::AddFont(const TCHAR * fullname, HDC hDC)
  299. {
  300.     PANOSE panose;
  301.     TCHAR  facename[MAX_PATH];
  302.  
  303.     if ( GetPANOSE(hDC, fullname, & panose, facename) )
  304.     {
  305.         assert(m_nFonts<MAX_FONTS);
  306.  
  307.         if ( m_nFonts < MAX_FONTS )
  308.         {
  309.             _tcscpy(m_TypeFace[m_nFonts], facename);
  310.             m_Panose[m_nFonts] = panose;
  311.  
  312.             m_nFonts ++;
  313.         }
  314.         
  315.         m_Fonts.AddItem( 0, fullname);
  316.         m_Fonts.AddItem( 1, facename);
  317.         
  318.         m_Fonts.AddItem( 2, PAN_FAMILY  [panose.bFamilyType]);
  319.         m_Fonts.AddItem( 3, PAN_SERIF   [panose.bSerifStyle]);
  320.         m_Fonts.AddItem( 4, PAN_WEIGHT  [panose.bWeight]);
  321.         m_Fonts.AddItem( 5, PAN_PROP    [panose.bProportion]);
  322.         m_Fonts.AddItem( 6, PAN_CONTRAST[panose.bContrast]);
  323.         m_Fonts.AddItem( 7, PAN_STROKE  [panose.bStrokeVariation]);
  324.         m_Fonts.AddItem( 8, PAN_ARM     [panose.bArmStyle]);
  325.         m_Fonts.AddItem( 9, PAN_LETT    [panose.bLetterform]);
  326.         m_Fonts.AddItem(10, PAN_MIDLINE [panose.bMidline]);
  327.         m_Fonts.AddItem(11, PAN_XHEIGHT [panose.bXHeight]);
  328.     }
  329.     else
  330.         assert(false);
  331. }
  332.  
  333.  
  334. void KPanoseView::ListPANOSE(void)
  335. {
  336.     const TCHAR Key_Fonts[] = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts");
  337.  
  338.     HKEY hKey;
  339.  
  340.     HDC hDC = GetDC(NULL);
  341.  
  342.     m_nFonts = 0;
  343.  
  344.     if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, Key_Fonts, 0, KEY_READ, & hKey)==ERROR_SUCCESS )
  345.     {
  346.         for (int i=0; ; i++)
  347.         {
  348.             TCHAR szValueName[MAX_PATH];
  349.             BYTE  szValueData[MAX_PATH];
  350.  
  351.             DWORD nValueNameLen = MAX_PATH;
  352.             DWORD nValueDataLen = MAX_PATH;
  353.             DWORD dwType;
  354.  
  355.             if ( RegEnumValue(hKey, i, szValueName, & nValueNameLen, NULL,
  356.                     & dwType, szValueData, & nValueDataLen) != ERROR_SUCCESS )
  357.                 break;
  358.  
  359.             // szValueName font name
  360.             // szValueData file name
  361.  
  362.             TCHAR * p = _tcschr(szValueName, '(');
  363.             if ( p && p[1]=='T' ) // (TrueType)
  364.             {
  365.                 * p = 0;
  366.  
  367.                 p = _tcschr(szValueName, '&'); // Font collection: A & B
  368.  
  369.                 if ( p )
  370.                 {
  371.                     *p=0;
  372.                     AddFont(szValueName, hDC);
  373.                     AddFont(p+1, hDC);
  374.                 }
  375.                 else
  376.                     AddFont(szValueName, hDC);
  377.             }
  378.         }
  379.         
  380.         RegCloseKey(hKey);
  381.     }
  382.  
  383.     ReleaseDC(NULL, hDC);
  384. }
  385.  
  386.  
  387. // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Panose
  388. void Map(void)
  389. {
  390. /*    KFontMapper mapper;
  391.  
  392.     mapper.SetFontList(s_panfonts, NUM_PANFONTS);
  393.  
  394.     unsigned short Order[3];
  395.     unsigned short Score[3];
  396.  
  397.     int result = mapper.PickFonts(& s_panfonts[1], Order, Score, 3);
  398.  
  399.     int i = 0;
  400. */
  401. }
  402.  
  403.  
  404. bool KPanoseView::Initialize(HINSTANCE hInstance, KStatusWindow * pStatus, HWND hWndFrame)
  405. {
  406.     m_hFrame    = hWndFrame;
  407.     m_hInst     = hInstance;
  408.     m_pStatus   = pStatus;
  409.  
  410.     RegisterClass(_T("PanoseViewClass"), hInstance);
  411.         
  412.     return true;
  413. }
  414.  
  415.  
  416. LRESULT KPanoseView::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  417. {
  418.     switch( uMsg )
  419.     {
  420.         case WM_CREATE:
  421.             m_hWnd        = hWnd;
  422.             m_hViewMenu = LoadMenu(m_hInst, MAKEINTRESOURCE(IDR_PANOSE));
  423.  
  424.             {
  425.                 RECT rect;
  426.  
  427.                 GetClientRect(m_hWnd, & rect);
  428.                 m_Fonts.Create(hWnd, 101, 0, 0, rect.right, rect.bottom, m_hInst);
  429.             }
  430.  
  431.             m_Fonts.AddColumn( 0, 100, "Original");
  432.             m_Fonts.AddColumn( 1, 100, "Typeface");
  433.  
  434.             m_Fonts.AddColumn( 2, 100, "Family");
  435.             m_Fonts.AddColumn( 3, 100, "Serif");
  436.             m_Fonts.AddColumn( 4, 100, "Weight");
  437.             m_Fonts.AddColumn( 5, 100, "Proportion");
  438.             m_Fonts.AddColumn( 6, 100, "Contract");
  439.             m_Fonts.AddColumn( 7, 100, "Stroke");
  440.             m_Fonts.AddColumn( 8, 100, "Arm");
  441.             m_Fonts.AddColumn( 9, 100, "Letterform");
  442.             m_Fonts.AddColumn(10, 100, "Midline");
  443.             m_Fonts.AddColumn(11, 100, "XHeight");
  444.  
  445.             ListPANOSE();
  446.             return 0;
  447.  
  448.         case WM_SIZE:
  449.             MoveWindow(m_Fonts.GetHWND(), 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);    
  450.             return 0;
  451.  
  452.         case WM_NOTIFY:
  453.             if (wParam == 101)
  454.             {
  455.                 NM_LISTVIEW * pInfo = (NM_LISTVIEW *) lParam;
  456.                 
  457.                 if ( (pInfo->hdr.code == NM_RCLICK) && (pInfo->iItem != -1) ) 
  458.                 {                    
  459.                     POINT pt = pInfo->ptAction;
  460.                     
  461.                     ClientToScreen(m_hWnd, & pt);
  462.                     
  463.                     HMENU hMenu = LoadMenu(m_hInst, MAKEINTRESOURCE(IDR_POPUP));
  464.  
  465.                     int id = TrackPopupMenu(GetSubMenu(hMenu, 0), TPM_RIGHTBUTTON | TPM_TOPALIGN | TPM_LEFTALIGN | TPM_RETURNCMD | TPM_NONOTIFY,
  466.                                  pt.x, pt.y, 0, m_hWnd, NULL);
  467.  
  468.                     DestroyMenu(hMenu);
  469.  
  470.                     if ( id==IDM_PANOSE_MATCH )
  471.                     {
  472.                         TCHAR fontname[MAX_PATH];
  473.  
  474.                         m_Fonts.GetItemText(pInfo->iItem, 1, fontname, MAX_PATH);
  475.  
  476.                         KFontMapper mapper;
  477.  
  478.                         mapper.SetFontList(m_Panose, m_nFonts);
  479.  
  480.                         unsigned short Order[10];
  481.                         unsigned short Score[10];
  482.  
  483.                         int result = mapper.PickFonts(& m_Panose[pInfo->iItem], Order, Score, 10);
  484.  
  485.                         char temp[MAX_PATH];
  486.  
  487.                         temp[0] = 0;
  488.                         for (int i=0; i<result; i++)
  489.                             wsprintf( temp + _tcslen(temp), "%d\t%d\t%s\n", i, Score[i], m_TypeFace[Order[i]]);
  490.  
  491.                         MyMessageBox(NULL, temp, fontname, MB_OK, IDI_TEXT);
  492.  
  493.                         return TRUE;
  494.                     }
  495.  
  496.                 }
  497.             }
  498.  
  499.         default:
  500.             return CommonMDIChildProc(hWnd, uMsg, wParam, lParam, m_hViewMenu, 3);
  501.     }
  502. }
  503.