This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| Simple Font Generator Submitted by

I know that a font generator has already been posted in the COTD, but this is a VERY simple version (all done in C, and should be able to just drop into an existing application). The source is commented, and is actually (IMO) pretty easy to understand (like I said, it's simple.) This code could even be used to generate dynamic strings for complex onscreen text (such as unicode for Japanese or Chinese languages). Infact, this code was inspired by a posting on OpenGL.org's Advanced fourm about how to display Chinese in OpenGL (though I don't personally use it that way, I use the many quads method and one texture). - Matt Williams

Currently browsing [FontGen.zip] (21,027 bytes) - [FontGen.c] - (5,670 bytes)

    #include <windows.h>
    #include <stdio.h>

    // Some default parameters:
    int FontWidth=256, FontHeight=256;
    int NumCellWidth=16, NumCellHeight=16;

    // TGA output function and struct
    typedef struct
    {
    	int Width, Height;
    	unsigned long Depth;
    	unsigned char *Data;
    } Image_t;

    void TGA_PutData(char *file, Image_t *Image)
    {
    	FILE *stream;
    	unsigned char IDLength=0;
    	unsigned char ColorMapType=0, ColorMapStart=0, ColorMapLength=0, ColorMapDepth=0;
    	unsigned short XOffset=0, YOffset=0;
    	unsigned char ImageDescriptor=0, ImageType=0;

    	switch(Image->Depth)
    	{
    		case 8:
    			ImageType=3;
    			break;

    		case 16:
    		case 24:
    		case 32:
    			ImageType=2;
    			break;

    		default:
    			return;
    	}

    	if((stream=fopen(file, "wb"))==NULL)
    		return;

    	fwrite(&IDLength, sizeof(unsigned char), 1, stream);
    	fwrite(&ColorMapType, sizeof(unsigned char), 1, stream);
    	fwrite(&ImageType, sizeof(unsigned char), 1, stream);
    	fwrite(&ColorMapStart, sizeof(unsigned short), 1, stream);
    	fwrite(&ColorMapLength, sizeof(unsigned short), 1, stream);
    	fwrite(&ColorMapDepth, sizeof(unsigned char), 1, stream);
    	fwrite(&XOffset, sizeof(unsigned short), 1, stream);
    	fwrite(&XOffset, sizeof(unsigned short), 1, stream);
    	fwrite(&Image->Width, sizeof(unsigned short), 1, stream);
    	fwrite(&Image->Height, sizeof(unsigned short), 1, stream);
    	fwrite(&Image->Depth, sizeof(unsigned char), 1, stream);
    	fwrite(&ImageDescriptor, sizeof(unsigned char), 1, stream);

    	fwrite(Image->Data, Image->Width*Image->Height*(Image->Depth/8), 1, stream);

    	fclose(stream);
    }

    // Pulled this from some old ID Software source code, nothing special
    int CheckParm(char *parm, int argc, char **argv)
    {
    	int i;

    	for(i=1;i<argc;i++)
    	{
    		if(stricmp(parm, argv[i])==0)
    			return i;
    	}

    	return 0;
    }

    int main(int argc, char **argv)
    {
    	// General counters
    	int x, y, i;
    	// Bitmap info for CreateDIBSection
    	BITMAPINFO BitmapInfo;
    	// Bitmap handle
    	HBITMAP hBitmap=NULL;
    	// Font handle
    	HFONT hFont=NULL;
    	// Memory device context
    	HDC hDC=NULL;
    	// Font "cell" rect
    	RECT Rect;
    	// Cell width and height
    	int CellWidth, CellHeight;
    	// Bitmap pointer for the DC
    	unsigned char *Bitmap;
    	// Some more parameter stuff (Font name and output file name)
    	char *FontName=NULL;
    	char *OutputName=NULL;
    	// Output image struct
    	Image_t Image;

    	// Check the parameters
    	if((i=CheckParm("-w", argc, argv))!=0)
    		FontWidth=atoi(argv[i+1]);

    	if((i=CheckParm("-h", argc, argv))!=0)
    		FontHeight=atoi(argv[i+1]);

    	if((i=CheckParm("-cx", argc, argv))!=0)
    		NumCellWidth=atoi(argv[i+1]);

    	if((i=CheckParm("-cy", argc, argv))!=0)
    		NumCellHeight=atoi(argv[i+1]);

    	if((i=CheckParm("-f", argc, argv))!=0)
    		FontName=argv[i+1];

    	if((i=CheckParm("-o", argc, argv))!=0)
    		OutputName=argv[i+1];

    	if((i=CheckParm("-?", argc, argv))!=0)
    	{
    		fprintf(stderr, "Help:\n"
    						"-w [width] : Sets font width (defaults to 256)\n"
    						"-h [height] : Sets font height (defaults to 256)\n"
    						"-cx [numcellx] : Sets number of x cells (defaults to 16)\n"
    						"-cy [numcelly] : Sets numbers of y cells (defaults to 16)\n"
    						"-f \"Font Name\" : Sets font name (defaults to \"NULL\")\n"
    						"-o \"output.tga\" : Sets the output file name (defaults to \"font.tga\")\n\n"
    						"Standard Usage:\n"
    						"%s -w 256 -h 256 -f \"Courier New\"\n\n"
    						"Unicode Usage (warning! this generates a LARGE file):\n"
    						"%s -w 8192 -h 8192 -cx 256 -cy 256 -f \"MS PGothic\"\n", argv[0], argv[0]);
    		return -1;
    	}

    	// Calculate the cell width and height
    	CellWidth=FontWidth/NumCellWidth;
    	CellHeight=FontHeight/NumCellHeight;

    	// Set the bitmap info
    	memset(&BitmapInfo, 0, sizeof(BITMAPINFO));
    	BitmapInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
    	BitmapInfo.bmiHeader.biWidth=FontWidth;
    	BitmapInfo.bmiHeader.biHeight=FontHeight;
    	BitmapInfo.bmiHeader.biBitCount=24;
    	BitmapInfo.bmiHeader.biPlanes=1;

    	// Create the memory DC
    	hDC=CreateCompatibleDC(NULL);

    	if(hDC==NULL)
    	{
    		fprintf(stderr, "CreateCompatibleDC failed.");
    		return -2;
    	}

    	// Create the DIB section (to map the DC to a memory pointer)
    	hBitmap=CreateDIBSection(hDC, &BitmapInfo, DIB_RGB_COLORS, &Bitmap, NULL, 0);

    	if(hBitmap==NULL)
    	{
    		fprintf(stderr, "CreateDIBSection failed.");
    		return -2;
    	}

    	// Create a font based on the various parameters (mainly the character height and font name)
    	hFont=CreateFont(CellHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH, FontName);

    	if(hFont==NULL)
    	{
    		fprintf(stderr, "CreateFont failed.");
    		return -2;
    	}

    	// Select the objects
    	SelectObject(hDC, hBitmap);
    	SelectObject(hDC, hFont);

    	// Set the colors
    	SetBkColor(hDC, RGB(0, 0, 0));
    	SetTextColor(hDC, RGB(255, 255, 255));

    	// Draw the characters to the DC
    	for(i=0, y=0;y<NumCellHeight;y++)
    	{
    		for(x=0;x<NumCellWidth;x++)
    		{
    			unsigned short text[1]={ i++ };

    			Rect.left=CellWidth*x;
    			Rect.right=Rect.left+CellWidth;
    			Rect.top=CellHeight*y;
    			Rect.bottom=Rect.top+CellHeight;

    			DrawTextW(hDC, text, 1, &Rect, DT_CENTER);
    		}
    	}

    	// Set the image struct with the bitmap info
    	Image.Depth=BitmapInfo.bmiHeader.biBitCount;
    	Image.Width=BitmapInfo.bmiHeader.biWidth;
    	Image.Height=BitmapInfo.bmiHeader.biHeight;
    	Image.Data=Bitmap;
    	// Write the TGA image
    	TGA_PutData((OutputName==NULL)?"font.tga":OutputName, &Image);

    	// Delete the objects and DC
    	DeleteObject(hFont);
    	DeleteObject(hBitmap);
    	DeleteDC(hDC);

    	// Lets get the hell out of here!
    	return 0;
    }

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.