home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / Chapt_14 / Font / Raster.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-12  |  9.6 KB  |  354 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   : raster.cpp                                                             //
  10. //  Description: Raster/vector font decoding                                         //
  11. //  Version    : 1.00.000, May 31, 2000                                              //
  12. //-----------------------------------------------------------------------------------//
  13.  
  14. #define STRICT
  15. #define _WIN32_WINNT 0x0500
  16. #define NOCRYPT
  17.  
  18. #include <windows.h>
  19. #include <assert.h>
  20. #include <tchar.h>
  21.  
  22. #include "..\..\include\mmfile.h"
  23. #include "raster.h"
  24.  
  25. class KFontHeader20
  26. {
  27. public:
  28.     WORD        Version;              // 0x200 for version 2.0, 0x300 for version 3.00
  29.     DWORD       Size;                 // Size of whole file 
  30.     CHAR        Copyright[60];
  31.     WORD        Type;                 // Raster Font if Type & 1 == 0 
  32.     WORD        Points;               // Nominal Point size 
  33.     WORD        VertRes;              // Nominal Vertical resolution 
  34.     WORD        HorizRes;             // Nominal Horizontal resolution
  35.     WORD        Ascent;               
  36.     WORD        IntLeading;           
  37.     WORD        ExtLeading;           
  38.     BYTE        Italic;               
  39.     BYTE        Underline;            
  40.     BYTE        StrikeOut;            
  41.     WORD        Weight;               
  42.     BYTE        CharSet;              
  43.     WORD        PixWidth;             // width. 0 ==> Variable
  44.     WORD        PixHeight;            
  45.     BYTE        Family;               // Pitch and Family
  46.     WORD        AvgWidth;             // Width of character 'X' 
  47.     WORD        MaxWidth;             // Maximum width 
  48.     BYTE        FirstChar;            // First character defined in font
  49.     BYTE        LastChar;             // Last character defined in font 
  50.     BYTE        DefaultChar;          // Sub. for out of range chars. 
  51.     BYTE        BreakChar;            // Word Break Character 
  52.     WORD        WidthBytes;           // No.Bytes/row of Bitmap
  53.     DWORD       Device;               // Offset to Device Name string 
  54.     DWORD       Face;                 // Offset to Face Name String
  55.     DWORD       BitsPointer;          // Offset to Bit Map
  56.     DWORD       BitsOffset;           // Offset to Bit Map 
  57. };
  58.  
  59.  
  60. class KFontHeader30 : public KFontHeader20
  61. {
  62. public:
  63.     BYTE        fsDBfiller;              /* Word alignment for the offset table  */
  64.  
  65.     DWORD       fsFlags;              /* Bit flags                            */
  66.     WORD        fsAspace;             /* Global A space, if any               */
  67.     WORD        fsBspace;             /* Global B space, if any               */
  68.     WORD        fsCspace;             /* Global C space, if any               */
  69.     DWORD       fsColorPointer;       /* offset to color table, if any        */
  70.     DWORD       fsReserved[4];        /*                                      */
  71.     BYTE        fsCharOffset;         /* Area for storing the char. offsets   */
  72. };
  73.  
  74. typedef struct
  75. {
  76.     SHORT GIwidth;
  77.     SHORT GIoffset;
  78. }    GLYPHINFO_20;
  79.  
  80. typedef struct
  81. {
  82.      SHORT GIwidth;
  83.      LONG  GIoffset;
  84. } GLYPHINFO_30;
  85.  
  86.  
  87. int VectorCharOut(HDC hDC, int x, int y, int ch, const KFontHeader20 * pH, int sx=1, int sy=1)
  88. {
  89.     typedef struct
  90.     {
  91.         short offset;
  92.         short width;
  93.     }    VectorGlyph;
  94.  
  95.     const VectorGlyph * pGlyph = (const VectorGlyph *) ( (BYTE *) & pH->BitsOffset + 4);
  96.  
  97.     if ( (ch<pH->FirstChar) || (ch>pH->LastChar) )
  98.         ch = pH->DefaultChar;
  99.     else
  100.         ch -= pH->FirstChar;
  101.  
  102.     int width  = pGlyph[ch].width;
  103.     int length = pGlyph[ch+1].offset - pGlyph[ch].offset;
  104.  
  105.     signed char * pStroke = (signed char *) pH + pH->BitsOffset + pGlyph[ch].offset;
  106.     
  107.     int dx = 0; 
  108.     int dy = 0;
  109.  
  110.     while ( length>0 )
  111.     {
  112.         bool move = false;
  113.  
  114.         if ( pStroke[0]==-128 )
  115.         {
  116.             move = true; pStroke++; length --;
  117.         }
  118.  
  119.         if ( (pStroke[0]==0) && (pStroke[1]==0) && (pStroke[2]==0) )
  120.             break;
  121.  
  122.         dx += pStroke[0];
  123.         dy += pStroke[1];
  124.  
  125.         if ( move )
  126.             MoveToEx(hDC, x + dx*sx, y + dy*sy, NULL);
  127.         else
  128.             LineTo(hDC, x + dx*sx, y + dy*sy);
  129.  
  130.         pStroke += 2; length -= 2;
  131.     }
  132.  
  133.     return width * sx;
  134. }
  135.  
  136.  
  137. int CharOut(HDC hDC, int x, int y, int ch, KFontHeader20 * pH, int sx=1, int sy=1)
  138. {
  139.     GLYPHINFO_20 * pGlyph = (GLYPHINFO_20 *) ( (BYTE *) & pH->BitsOffset + 5);
  140.     
  141.     if ( (ch<pH->FirstChar) || (ch>pH->LastChar) )
  142.         ch = pH->DefaultChar;
  143.     else
  144.         ch -= pH->FirstChar;
  145.  
  146.     int width  = pGlyph[ch].GIwidth;
  147.     int height = pH->PixHeight;
  148.  
  149.     struct { BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[2]; } dib = 
  150.     { 
  151.         { sizeof(BITMAPINFOHEADER), width, -height, 1, 1, BI_RGB }, 
  152.         { { 0xFF, 0xFF, 0xFF, 0 }, { 0, 0, 0, 0 } }
  153.     };
  154.     
  155.     int bpl = ( width + 31 ) / 32 * 4;
  156.     BYTE data[64/8*64]; // enough for 64x64
  157.  
  158.     const BYTE * pPixel = (const BYTE *) pH + pGlyph[ch].GIoffset;
  159.     
  160.     for (int i=0; i<(width+7)/8; i++)
  161.     for (int j=0; j<height; j++)
  162.         data[bpl * j + i] = * pPixel ++;
  163.  
  164.     StretchDIBits(hDC, x, y, width * sx, height * sy, 0, 0, width, height, 
  165.                        data, (BITMAPINFO *) & dib, DIB_RGB_COLORS, SRCCOPY);
  166.  
  167.     return width * sx;
  168. }
  169.  
  170.  
  171. int Disp20(HDC hDC, int x0, int y0, KFontHeader20 * pH)
  172. {
  173.     char desp[MAX_PATH];
  174.     wsprintf(desp, "%d pts, %dx%d dpi, %dx%d pixel, avgw %d, maxw %d, charset %d",
  175.         pH->Points, pH->VertRes, pH->HorizRes, pH->PixWidth, pH->PixHeight, pH->AvgWidth, pH->MaxWidth,
  176.         pH->CharSet);
  177.     TextOut(hDC, x0, y0+10, desp, _tcslen(desp));
  178.     y0 += 40;
  179.  
  180.     int dy = pH->PixHeight + 2;
  181.     int dx = pH->MaxWidth  + 2;
  182.     int col;
  183.  
  184.     if ( pH->Points>24 )
  185.         col = 16;
  186.     else
  187.         col = 32;
  188.  
  189.     for (int ch = 0; ch<256; ch++)
  190.         if ( pH->Type & 1 )
  191.             VectorCharOut(hDC, x0 + dx * (ch%col), y0 + dy * (ch/col), ch, pH);
  192.         else
  193.             CharOut(hDC, x0 + dx * (ch%col), y0 + dy * (ch/col), ch, pH);
  194.  
  195.     return 60 + dy * (256/col);
  196. }
  197.  
  198.  
  199. int Disp30(HDC hDC, int x0, int y0, KFontHeader30 * pH)
  200. {
  201.     GLYPHINFO_30 * pGlyph = (GLYPHINFO_30 *) & pH->fsCharOffset;
  202.  
  203.     int height = pH->PixHeight;
  204.  
  205.     int no = pH->LastChar - pH->FirstChar + 1;
  206.  
  207.     for (int i=0; i<no; i++)
  208.     {
  209.         int width = pGlyph[i].GIwidth;
  210.  
  211.         const BYTE * pPixel = (const BYTE *) pH + pGlyph[i].GIoffset;
  212.             
  213.         for (int y=0; y<height; y++)
  214.         {
  215.             for (int x=0; x<(width+7)/8; x++)
  216.             {
  217.                 int xx = 0;
  218.                 for (int b=0x80; b!=0; b>>=1)
  219.                 {
  220.                     if ( pPixel[x] & b )
  221.                         SetPixel(hDC, i*20 + xx, y+10, RGB(0xFF, 0xFF, 0));
  222.                     else
  223.                         SetPixel(hDC, i*20 + xx, y+10, RGB(0, 0, 0xFF));
  224.                         
  225.                     xx ++;
  226.                 }
  227.                 pPixel ++;
  228.             }
  229.         }
  230.     }
  231.  
  232.     return 0;
  233. }
  234.  
  235. typedef struct 
  236. {
  237.      WORD    rnOffset;
  238.      WORD    rnLength;
  239.      WORD    rnFlags;
  240.      WORD    rnID;
  241.      WORD    rnHandle;
  242.      WORD    rnUsage;
  243. } NAMEINFO;
  244.  
  245. typedef struct 
  246. {
  247.      WORD        rtTypeID;
  248.      WORD        rtResourceCount;
  249.      DWORD       rtReserved;
  250.      NAMEINFO    rtNameInfo[1];
  251. } TYPEINFO;
  252.  
  253. typedef struct
  254. {
  255.     WORD     rscAlignShift;
  256.     TYPEINFO rscTypes[1];
  257. //    WORD     rscEndTypes;
  258. //    BYTE     rscResourceNames[];
  259. //    BYTE     rscEndNames;
  260. }    RESTABLE;
  261.  
  262.  
  263. int DecodeRasterFont(HDC hDC, const TCHAR * filename)
  264. {
  265.     KMemoryMappedFile bmpfont;
  266.  
  267.     int y = 40;
  268.  
  269.     KFontHeader20 * pFont = NULL;
  270.  
  271.     if ( bmpfont.Open(filename) )
  272.     {
  273.         TextOut(hDC, 10, 10, filename, _tcslen(filename));
  274.  
  275.         KFontHeader20 * pH;
  276.  
  277.         pH = (KFontHeader20 *) bmpfont.m_View;
  278.  
  279.         switch ( pH->Version )
  280.         {
  281.             case 0x200:    
  282.                 y += Disp20(hDC, 20, y, pH); 
  283.                 break;
  284.  
  285.             case 0x300: 
  286.                 y += Disp30(hDC, 20, y, (KFontHeader30 *) pH); 
  287.                 break;
  288.  
  289.             case IMAGE_DOS_SIGNATURE: // MZ
  290.                 {
  291.                     IMAGE_DOS_HEADER * pDOS = (IMAGE_DOS_HEADER *) pH;
  292.                     IMAGE_OS2_HEADER * pOS2 = (IMAGE_OS2_HEADER *) ( (BYTE *) pH + pDOS->e_lfanew);
  293.  
  294.                     RESTABLE * pResTable = (RESTABLE *) ((BYTE *) pOS2 + pOS2->ne_rsrctab);
  295.  
  296.                     int unit    = 1 << pResTable->rscAlignShift;
  297.  
  298.                     TYPEINFO * pTypeInfo = pResTable->rscTypes;
  299.  
  300.                     // search fir RT_FONT resource
  301.                     while ( pTypeInfo->rtTypeID!=0 )
  302.                     {
  303.                         if ( (pTypeInfo->rtTypeID & 0xFFF) == (WORD) RT_FONT )
  304.                             for (int i=0; i<pTypeInfo->rtResourceCount; i++)
  305.                             {
  306.                                 WORD offset = pTypeInfo->rtNameInfo[i].rnOffset * unit;
  307.  
  308.                                 pFont = (KFontHeader20 *) ((BYTE *) pH + offset);
  309.  
  310.                                 switch ( pFont->Version )
  311.                                 {
  312.                                     case 0x100:
  313.                                         y += Disp20(hDC, 20, y, pFont);
  314.                                         break;
  315.  
  316.                                     case 0x200:    
  317.                                         y += Disp20(hDC, 20, y, pFont); 
  318.                                         break;
  319.  
  320.                                     case 0x300: 
  321.                                         y += Disp30(hDC, 20, y, (KFontHeader30 *) pFont); 
  322.                                         break;
  323.                                 }
  324.                             }
  325.  
  326.                         pTypeInfo = (TYPEINFO *) & pTypeInfo[pTypeInfo->rtResourceCount];
  327.                     }
  328.                 }
  329.         }
  330.     }
  331.  
  332.     y+= 280;
  333.  
  334.     if ( pFont )
  335.     {
  336.         int x = 50;
  337.  
  338.         for (int i=1; i<10; i++)
  339.             if ( pFont->Type & 1 )
  340.             {
  341.                 HPEN hPen = CreatePen(PS_SOLID, i, 0);
  342.                 HGDIOBJ hOld = SelectObject(hDC, hPen);
  343.  
  344.                 x += VectorCharOut(hDC, x, y-pFont->Ascent*i, 'A', pFont, i, i) + 5;                            
  345.                 SelectObject(hDC, hOld);
  346.                 DeleteObject(hPen);
  347.             }
  348.             else
  349.                 x += CharOut(hDC, x, y-pFont->Ascent*i, 'A', pFont, i, i) + 5;
  350.     }        
  351.     
  352.     return y + 20;
  353. }
  354.