raster.cpp

来自「Windows 图形编程 书籍」· C++ 代码 · 共 354 行

CPP
354
字号
//-----------------------------------------------------------------------------------//
//              Windows Graphics Programming: Win32 GDI and DirectDraw               //
//                             ISBN  0-13-086985-6                                   //
//                                                                                   //
//  Written            by  Yuan, Feng                             www.fengyuan.com   //
//  Copyright (c) 2000 by  Hewlett-Packard Company                www.hp.com         //
//  Published          by  Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com      //
//                                                                                   //
//  FileName   : raster.cpp						                                     //
//  Description: Raster/vector font decoding                                         //
//  Version    : 1.00.000, May 31, 2000                                              //
//-----------------------------------------------------------------------------------//

#define STRICT
#define _WIN32_WINNT 0x0500
#define NOCRYPT

#include <windows.h>
#include <assert.h>
#include <tchar.h>

#include "..\..\include\mmfile.h"
#include "raster.h"

class KFontHeader20
{
public:
    WORD        Version;              // 0x200 for version 2.0, 0x300 for version 3.00
    DWORD       Size;                 // Size of whole file 
    CHAR        Copyright[60];
    WORD        Type;                 // Raster Font if Type & 1 == 0 
    WORD        Points;               // Nominal Point size 
    WORD        VertRes;              // Nominal Vertical resolution 
    WORD        HorizRes;             // Nominal Horizontal resolution
    WORD        Ascent;               
    WORD        IntLeading;           
    WORD        ExtLeading;           
    BYTE        Italic;               
    BYTE        Underline;            
    BYTE        StrikeOut;            
    WORD        Weight;               
    BYTE        CharSet;              
    WORD        PixWidth;             // width. 0 ==> Variable
    WORD        PixHeight;            
    BYTE        Family;               // Pitch and Family
    WORD        AvgWidth;             // Width of character 'X' 
    WORD        MaxWidth;             // Maximum width 
    BYTE        FirstChar;            // First character defined in font
    BYTE        LastChar;             // Last character defined in font 
    BYTE        DefaultChar;          // Sub. for out of range chars. 
    BYTE        BreakChar;            // Word Break Character 
    WORD        WidthBytes;           // No.Bytes/row of Bitmap
    DWORD       Device;               // Offset to Device Name string 
    DWORD       Face;                 // Offset to Face Name String
    DWORD       BitsPointer;          // Offset to Bit Map
    DWORD       BitsOffset;           // Offset to Bit Map 
};


class KFontHeader30 : public KFontHeader20
{
public:
	BYTE		fsDBfiller;			  /* Word alignment for the offset table  */

    DWORD       fsFlags;              /* Bit flags                            */
    WORD        fsAspace;             /* Global A space, if any               */
    WORD        fsBspace;             /* Global B space, if any               */
    WORD        fsCspace;             /* Global C space, if any               */
    DWORD       fsColorPointer;       /* offset to color table, if any        */
    DWORD       fsReserved[4];        /*                                      */
    BYTE        fsCharOffset;         /* Area for storing the char. offsets   */
};

typedef struct
{
	SHORT GIwidth;
    SHORT GIoffset;
}	GLYPHINFO_20;

typedef struct
{
     SHORT GIwidth;
     LONG  GIoffset;
} GLYPHINFO_30;


int VectorCharOut(HDC hDC, int x, int y, int ch, const KFontHeader20 * pH, int sx=1, int sy=1)
{
	typedef struct
	{
		short offset;
		short width;
	}	VectorGlyph;

	const VectorGlyph * pGlyph = (const VectorGlyph *) ( (BYTE *) & pH->BitsOffset + 4);

	if ( (ch<pH->FirstChar) || (ch>pH->LastChar) )
		ch = pH->DefaultChar;
	else
		ch -= pH->FirstChar;

	int width  = pGlyph[ch].width;
	int length = pGlyph[ch+1].offset - pGlyph[ch].offset;

	signed char * pStroke = (signed char *) pH + pH->BitsOffset + pGlyph[ch].offset;
	
	int dx = 0; 
	int dy = 0;

	while ( length>0 )
	{
		bool move = false;

		if ( pStroke[0]==-128 )
		{
			move = true; pStroke++; length --;
		}

		if ( (pStroke[0]==0) && (pStroke[1]==0) && (pStroke[2]==0) )
			break;

		dx += pStroke[0];
		dy += pStroke[1];

		if ( move )
			MoveToEx(hDC, x + dx*sx, y + dy*sy, NULL);
		else
			LineTo(hDC, x + dx*sx, y + dy*sy);

		pStroke += 2; length -= 2;
	}

	return width * sx;
}


int CharOut(HDC hDC, int x, int y, int ch, KFontHeader20 * pH, int sx=1, int sy=1)
{
	GLYPHINFO_20 * pGlyph = (GLYPHINFO_20 *) ( (BYTE *) & pH->BitsOffset + 5);
	
	if ( (ch<pH->FirstChar) || (ch>pH->LastChar) )
		ch = pH->DefaultChar;
	else
		ch -= pH->FirstChar;

	int width  = pGlyph[ch].GIwidth;
	int height = pH->PixHeight;

	struct { BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[2]; } dib = 
	{ 
		{ sizeof(BITMAPINFOHEADER), width, -height, 1, 1, BI_RGB }, 
		{ { 0xFF, 0xFF, 0xFF, 0 }, { 0, 0, 0, 0 } }
	};
    
	int bpl = ( width + 31 ) / 32 * 4;
	BYTE data[64/8*64]; // enough for 64x64

	const BYTE * pPixel = (const BYTE *) pH + pGlyph[ch].GIoffset;
	
	for (int i=0; i<(width+7)/8; i++)
	for (int j=0; j<height; j++)
		data[bpl * j + i] = * pPixel ++;

	StretchDIBits(hDC, x, y, width * sx, height * sy, 0, 0, width, height, 
					   data, (BITMAPINFO *) & dib, DIB_RGB_COLORS, SRCCOPY);

	return width * sx;
}


int Disp20(HDC hDC, int x0, int y0, KFontHeader20 * pH)
{
	char desp[MAX_PATH];
	wsprintf(desp, "%d pts, %dx%d dpi, %dx%d pixel, avgw %d, maxw %d, charset %d",
		pH->Points, pH->VertRes, pH->HorizRes, pH->PixWidth, pH->PixHeight, pH->AvgWidth, pH->MaxWidth,
		pH->CharSet);
	TextOut(hDC, x0, y0+10, desp, _tcslen(desp));
	y0 += 40;

	int dy = pH->PixHeight + 2;
	int dx = pH->MaxWidth  + 2;
	int col;

	if ( pH->Points>24 )
		col = 16;
	else
		col = 32;

	for (int ch = 0; ch<256; ch++)
		if ( pH->Type & 1 )
			VectorCharOut(hDC, x0 + dx * (ch%col), y0 + dy * (ch/col), ch, pH);
		else
			CharOut(hDC, x0 + dx * (ch%col), y0 + dy * (ch/col), ch, pH);

	return 60 + dy * (256/col);
}


int Disp30(HDC hDC, int x0, int y0, KFontHeader30 * pH)
{
	GLYPHINFO_30 * pGlyph = (GLYPHINFO_30 *) & pH->fsCharOffset;

	int height = pH->PixHeight;

	int no = pH->LastChar - pH->FirstChar + 1;

	for (int i=0; i<no; i++)
	{
		int width = pGlyph[i].GIwidth;

		const BYTE * pPixel = (const BYTE *) pH + pGlyph[i].GIoffset;
			
		for (int y=0; y<height; y++)
		{
			for (int x=0; x<(width+7)/8; x++)
			{
				int xx = 0;
				for (int b=0x80; b!=0; b>>=1)
				{
					if ( pPixel[x] & b )
						SetPixel(hDC, i*20 + xx, y+10, RGB(0xFF, 0xFF, 0));
					else
						SetPixel(hDC, i*20 + xx, y+10, RGB(0, 0, 0xFF));
						
					xx ++;
				}
				pPixel ++;
			}
		}
	}

	return 0;
}

typedef struct 
{
     WORD	rnOffset;
     WORD	rnLength;
     WORD	rnFlags;
     WORD	rnID;
     WORD	rnHandle;
     WORD	rnUsage;
} NAMEINFO;

typedef struct 
{
     WORD        rtTypeID;
     WORD        rtResourceCount;
     DWORD       rtReserved;
     NAMEINFO    rtNameInfo[1];
} TYPEINFO;

typedef struct
{
	WORD     rscAlignShift;
	TYPEINFO rscTypes[1];
//	WORD     rscEndTypes;
//	BYTE     rscResourceNames[];
//	BYTE     rscEndNames;
}	RESTABLE;


int DecodeRasterFont(HDC hDC, const TCHAR * filename)
{
    KMemoryMappedFile bmpfont;

	int y = 40;

	KFontHeader20 * pFont = NULL;

    if ( bmpfont.Open(filename) )
    {
		TextOut(hDC, 10, 10, filename, _tcslen(filename));

        KFontHeader20 * pH;

		pH = (KFontHeader20 *) bmpfont.m_View;

		switch ( pH->Version )
		{
			case 0x200:	
				y += Disp20(hDC, 20, y, pH); 
				break;

			case 0x300: 
				y += Disp30(hDC, 20, y, (KFontHeader30 *) pH); 
				break;

			case IMAGE_DOS_SIGNATURE: // MZ
				{
					IMAGE_DOS_HEADER * pDOS = (IMAGE_DOS_HEADER *) pH;
					IMAGE_OS2_HEADER * pOS2 = (IMAGE_OS2_HEADER *) ( (BYTE *) pH + pDOS->e_lfanew);

					RESTABLE * pResTable = (RESTABLE *) ((BYTE *) pOS2 + pOS2->ne_rsrctab);

					int unit	= 1 << pResTable->rscAlignShift;

					TYPEINFO * pTypeInfo = pResTable->rscTypes;

					// search fir RT_FONT resource
					while ( pTypeInfo->rtTypeID!=0 )
					{
						if ( (pTypeInfo->rtTypeID & 0xFFF) == (WORD) RT_FONT )
							for (int i=0; i<pTypeInfo->rtResourceCount; i++)
							{
								WORD offset = pTypeInfo->rtNameInfo[i].rnOffset * unit;

								pFont = (KFontHeader20 *) ((BYTE *) pH + offset);

								switch ( pFont->Version )
								{
									case 0x100:
										y += Disp20(hDC, 20, y, pFont);
										break;

									case 0x200:	
										y += Disp20(hDC, 20, y, pFont); 
										break;

									case 0x300: 
										y += Disp30(hDC, 20, y, (KFontHeader30 *) pFont); 
										break;
								}
							}

						pTypeInfo = (TYPEINFO *) & pTypeInfo[pTypeInfo->rtResourceCount];
					}
				}
		}
	}

	y+= 280;

	if ( pFont )
	{
		int x = 50;

		for (int i=1; i<10; i++)
			if ( pFont->Type & 1 )
			{
				HPEN hPen = CreatePen(PS_SOLID, i, 0);
				HGDIOBJ hOld = SelectObject(hDC, hPen);

				x += VectorCharOut(hDC, x, y-pFont->Ascent*i, 'A', pFont, i, i) + 5;							
				SelectObject(hDC, hOld);
				DeleteObject(hPen);
			}
			else
				x += CharOut(hDC, x, y-pFont->Ascent*i, 'A', pFont, i, i) + 5;
	}		
	
	return y + 20;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?