// 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 ) { 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; }