halflife-wasteland-sdk/utils/makevfont/makevfont.cpp

379 lines
8.2 KiB
C++
Raw Permalink Normal View History

2000-06-05 00:00:00 +00:00
// makevfont.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "fileimage.h"
#include "vfontdata.h"
bool CreateVFont(
char *pOutFile,
char *pFontName,
int pointSize,
bool bItalic,
bool bBold,
bool bUnderline)
{
HFONT hFont, hOldFont;
int i;
char theChar;
SIZE charSize;
int bitmapCharWidth, bitmapCharHeight;
HDC hDC, hMemDC;
bool bRet;
RECT rc, rcChar;
HBITMAP hBitmap, hOldBitmap;
BITMAPINFOHEADER *pbmheader;
BITMAPINFO tempbmi;
BITMAPINFO *pbmi;
unsigned char *bits;
int nScans;
FileImage fileImage;
FILE *fp;
hFont = hOldFont = NULL;
hDC = hMemDC = NULL;
hBitmap = hOldBitmap = NULL;
pbmi = NULL;
bRet = true;
// Make the font.
hFont = CreateFont(
pointSize,
0,
0,
0,
bBold ? FW_HEAVY : FW_MEDIUM,
bItalic,
bUnderline,
0,
ANSI_CHARSET,
OUT_TT_PRECIS,
CLIP_DEFAULT_PRECIS,
PROOF_QUALITY,
VARIABLE_PITCH | FF_DONTCARE,
pFontName);
if(!hFont)
{
printf("CreateFont failed!\n");
goto HANDLE_ERROR;
}
hDC = GetDC(NULL);
hMemDC = CreateCompatibleDC(hDC);
if(!hMemDC)
{
printf("CreateCompatibleDC failed!\n");
goto HANDLE_ERROR;
}
hOldFont = (HFONT)SelectObject(hMemDC, hFont);
// Figure out the biggest character.
bitmapCharWidth = bitmapCharHeight = 0;
for(i=0; i < NUM_VFONT_CHARS; i++)
{
theChar = (char)i;
if(!GetTextExtentPoint32(hMemDC, &theChar, 1, &charSize))
{
printf("GetTextExtentPoint32 failed!\n");
goto HANDLE_ERROR;
}
if(charSize.cx > bitmapCharWidth)
bitmapCharWidth = charSize.cx;
if(charSize.cy > bitmapCharHeight)
bitmapCharHeight = charSize.cy;
}
// We get 1 pixel of padding because, for some reason, Windows likes to clip off the left pixel
// on some letters like W.
bitmapCharWidth++;
// Setup our bitmap.
hBitmap = CreateBitmap(bitmapCharWidth * NUM_VFONT_CHARS, bitmapCharHeight, 1, 1, NULL);
if(!hBitmap)
{
printf("CreateBitmap failed!\n");
goto HANDLE_ERROR;
}
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
SetTextColor( hMemDC, 0x00ffffff );
SetBkMode( hMemDC, TRANSPARENT );
// Fill the background.
rc.left = rc.top = 0;
rc.right = bitmapCharWidth * NUM_VFONT_CHARS;
rc.bottom = bitmapCharHeight;
FillRect( hMemDC, &rc, (HBRUSH)GetStockObject( BLACK_BRUSH ) );
// Draw characters in.
for(i=0; i < NUM_VFONT_CHARS; i++)
{
// Draw the letter in the first slot for a letter.
rcChar.left = 0;
rcChar.top = 0;
rcChar.right = bitmapCharWidth;
rcChar.bottom = bitmapCharHeight;
FillRect( hMemDC, &rcChar, (HBRUSH)GetStockObject( BLACK_BRUSH ) );
if(i != '\t')
{
rcChar.left = 1; // 1-pixel border for letters like W...
theChar = (char)i;
DrawText(hMemDC, &theChar, 1, &rcChar, DT_NOPREFIX | DT_LEFT);
// Blit into the correct spot (by drawing/blitting, it sort of automatically clips the letter into
// its box (Windows seems to want to draw some of them out of their bounding box).
rcChar.left = i * bitmapCharWidth;
rcChar.top = 0;
rcChar.right = (i+1) * bitmapCharWidth;
rcChar.bottom = bitmapCharHeight;
if(!BitBlt(hMemDC,
i * bitmapCharWidth,
0,
bitmapCharWidth,
bitmapCharHeight,
hMemDC,
0,
0,
SRCCOPY))
{
printf("BitBlt failed!\n");
goto HANDLE_ERROR;
}
}
}
// Get the bits out.
memset(&tempbmi, 0, sizeof(BITMAPINFO));
pbmheader = ( BITMAPINFOHEADER * )&tempbmi;
pbmheader->biSize = sizeof( BITMAPINFOHEADER );
pbmheader->biWidth = bitmapCharWidth * NUM_VFONT_CHARS;
pbmheader->biHeight = -bitmapCharHeight;
pbmheader->biPlanes = 1;
pbmheader->biBitCount = 32;
pbmheader->biCompression = BI_RGB;
// Figure out how many bytes to allocate and setup a buffer.
nScans = GetDIBits(hMemDC, hBitmap, 0, bitmapCharHeight, NULL, &tempbmi, DIB_RGB_COLORS);
pbmi = ( BITMAPINFO * )malloc( sizeof ( BITMAPINFOHEADER ) + 2 * sizeof( RGBQUAD ) + pbmheader->biSizeImage );
memcpy( pbmi, &tempbmi, sizeof( BITMAPINFO ) );
bits = ( unsigned char * )pbmi + sizeof( BITMAPINFOHEADER ) + 2 * sizeof( RGBQUAD );
// Read the bits in.
nScans = GetDIBits(hMemDC, hBitmap, 0, bitmapCharHeight, bits, pbmi, DIB_RGB_COLORS);
if(nScans == 0)
{
printf("GetDIBits failed!\n");
goto HANDLE_ERROR;
}
// Save as a PCX/TGA file.
fp = fopen(pOutFile, "wb");
if(!fp)
{
printf("fopen(%s, \"wb\") failed!\n", pOutFile);
goto HANDLE_ERROR;
}
fileImage.m_Width = bitmapCharWidth * NUM_VFONT_CHARS;
fileImage.m_Height = bitmapCharHeight;
fileImage.m_pData = (unsigned char*)bits;
Save32BitTGA(fp, &fileImage);
fileImage.Clear();
fclose(fp);
goto CLEANUP;
HANDLE_ERROR:;
bRet = false;
CLEANUP:;
if(hMemDC)
{
if(hOldBitmap)
SelectObject(hMemDC, hOldBitmap);
if(hOldFont)
SelectObject(hMemDC, hOldFont);
DeleteDC(hMemDC);
}
if(hBitmap)
{
DeleteObject(hBitmap);
}
if(hFont)
{
DeleteObject(hFont);
}
if(pbmi)
{
free(pbmi);
}
return true;
}
/*
// Writes out a test string to "testout.tga" using the font it just generated for debugging purposes.
void DoTest(char *pFilename)
{
// TEST.
FILE *fp;
VFontData fontData;
char *pStr = "Blah blah blah. This is a string of text I am printing out. \"Here is something in quotes, blah blah blah.\"";
int len, curXOffset, iChar, width, x, y;
HWND hWnd;
HDC hDC;
FileImage outImage;
fp=fopen(pFilename, "rb");
LoadVFontDataFrom32BitTGA(fp, &fontData);
int spacing=1;
len = strlen(pStr);
outImage.m_Width = fontData.m_BitmapCharWidth * len + len*spacing;
outImage.m_Height = fontData.m_BitmapCharHeight;
outImage.m_pData = new unsigned char[outImage.m_Width * outImage.m_Height * 4];
memset(outImage.m_pData, 0, outImage.m_Width*outImage.m_Height);
hWnd = GetDesktopWindow();
hDC = GetDC(hWnd);
curXOffset = 0;
for(iChar=0; iChar < len; iChar++)
{
width = fontData.m_CharWidths[(unsigned char)pStr[iChar]]+1;
for(y=0; y < fontData.m_BitmapCharHeight; y++)
{
for(x=0; x < width; x++)
{
if(fontData.m_pBitmap[y*fontData.GetLineWidth()+x+(unsigned char)pStr[iChar]*fontData.m_BitmapCharWidth])
{
*((unsigned long*)&outImage.m_pData[(y*outImage.m_Width+curXOffset+x)*4]) = 0xFFFFFFFF;
}
else
{
*((long*)&outImage.m_pData[(y*outImage.m_Width+curXOffset+x)*4]) = 0;
}
}
for(x=0; x < spacing; x++)
{
*((long*)&outImage.m_pData[(y*outImage.m_Width+curXOffset+width+x)*4]) = 0;
}
}
curXOffset += width + spacing;
}
ReleaseDC(hWnd, hDC);
fclose(fp);
fp = fopen("testout.tga", "wb");
Save32BitTGA(fp, &outImage);
fclose(fp);
}
*/
int main(int argc, char* argv[])
{
char fontName[256];
int pointSize;
bool bItalic, bBold, bUnderline;
int i;
// Setup defaults.
strcpy(fontName, "Arial");
pointSize = 7;
bItalic = bBold = bUnderline = false;
printf("makevfont.exe Version 1.0 by Valve (%s)\n", __DATE__ );
printf ("----- Creating Font ----\n");
// Read parameters in.
for (i=1 ; i<argc ; i++)
{
if (!strcmp(argv[i],"-font"))
{
strcpy( fontName, argv[i+1] );
i++;
}
else if (!strcmp(argv[i],"-pointsize"))
{
if (i + 1 >= argc )
{
printf( "MakeVFont: Insufficient point sizes specified\n" );
return -1;
}
pointSize = atoi( argv[i+1] );
i += 1;
}
else if (!strcmp(argv[i],"-italic"))
{
bItalic = true;
printf ( "italic set\n");
}
else if (!strcmp(argv[i],"-bold"))
{
bBold = true;
printf ( "bold set\n");
}
else if (!strcmp(argv[i],"-underline"))
{
bUnderline = true;
printf ( "underline set\n");
}
else if ( argv[i][0] == '-' )
{
printf("Unknown option \"%s\"", argv[i]);
return -1;
}
else
break;
}
if ( i != argc - 1 )
{
printf("usage: makevfont [-font \"fontname\"] [-italic] [-underline] [-bold] [-pointsize size] outfile");
return -1;
}
CreateVFont(
argv[argc-1],
fontName,
pointSize,
bItalic,
bBold,
bUnderline);
return 0;
}