View Full Version : Legay curiosities and font rendering

02-18-2010, 06:02 AM
So, been sort of working on this win32 font issue for a while now. I know there are a tonne of other librarys out there for font rendering, but I like the wglUseFontBitmaps for simplicity, Unicode support, ability to use the Win32 text functions for calculating the dimensions of text, to centre text etc ..

But the bitmap fonts have one major limitation, the bitmaps are binary images and thus can not do transparency, and thus can not be anti-aliased.

Thus I set about trying to write a direct plug in replacement for this. The first thing that made me really wonder was the
glbitmap function. Not talked about in the API is the fact the bitmap function takes images that are inverted (Win32 layout) instead of the standard OGL layout that gldrawpixels takes. I find this most strange. Even more strange, the glbitmap function can put the raster position outside the viewport for rendering, so that you can render text that will overlap into the viewport, while you can't do this with the glrasterpos functions. This makes me think that maybe microsoft simply wrote this function for their text function. I can't see any other reason for glbitmap existing.

Heres a screeny of my text rendering in my media centre software.
http://i126.photobucket.com/albums/p95/dukeeeey/th_text.png (http://s126.photobucket.com/albums/p95/dukeeeey/?action=view&current=text.png)

And here is the code, should just be a drop in replacement for the standard Win32 text functions, and should look the same, only better. Enjoy :)

#include <windows.h>
#include <gl\gl.h>
#include <stdio.h>
#include <math.h>

void remapColourRange(UCHAR *data, int numberOfItems) {

for(int i=0; i<numberOfItems; i++) {
data[i] = (data[i] * 255) / 64;

void copyLine(UCHAR *in, UCHAR *out, int width) {

for(int i=0; i<width; i++) {
out[i] = in[i];

void flipImage(UCHAR *data, int width, int height) {

UCHAR *temp;
DWORD offset;
DWORD offset2;

offset = 0;
offset2 = 0;
temp = new UCHAR[width];

for(int i=0; i<height/2; i++) {

offset = ((width+3) & ~3) * i;
copyLine(data+offset,temp,width); // copy bottom line

offset2 = ((width+3) & ~3) * (height-i-1);
copyLine(data+offset2,data+offset,width); // copy top line to bottom

copyLine(temp,data+offset2,width); // temp line to top

delete []temp;

void convertLine(UCHAR *in, UCHAR *out, int width) {

for(int i=0; i<width*4; i+=4) {
out[i+0] = 255;
out[i+1] = 255;
out[i+2] = 255;
out[i+3] = in[i/4];

void convertToRGB(UCHAR *in, UCHAR *out, int width, int height) {

int offset;
int offset2;

offset = (width+3) & ~3;
offset2 = (((width*4)+3) & ~3);

for(int i=0; i<height; i++) {

BOOL createFont(HDC hdc, DWORD first, DWORD count, DWORD listBase) {

MAT2 mat2;
DWORD size;
UCHAR *data;

// safety checks

if(!count) return FALSE;
if(!hdc) return FALSE;

// initiate variables

size = 0;
data = NULL;

// identity matrix

memset(&amp;mat2, 0, sizeof(mat2));
mat2.eM11.value = 1; mat2.eM21.value = 0;
mat2.eM12.value = 0; mat2.eM22.value = 1;


for(DWORD i = 0 ; i< count; i++) {


// get size of the structure first

size = GetGlyphOutline(hdc,first+i,GGO_GRAY8_BITMAP, &amp;gm, 0, NULL, &amp;mat2);
if(size == GDI_ERROR) { glEndList(); continue; }

if(size) {

data = new UCHAR[size];

GetGlyphOutline(hdc,first+i,GGO_GRAY8_BITMAP,&amp;gm,s ize,data,&amp;mat2);

flipImage (data,gm.gmBlackBoxX,gm.gmBlackBoxY);

RGBData = new UCHAR[(((gm.gmBlackBoxX*4)+3) & ~3) * gm.gmBlackBoxY ];

convertToRGB(data,RGBData,gm.gmBlackBoxX,gm.gmBlac kBoxY);

glEnable (GL_BLEND);

glBitmap (0,0,0,0,(GLfloat)gm.gmptGlyphOrigin.x,(GLfloat)gm .gmptGlyphOrigin.y-(GLfloat)gm.gmBlackBoxY,NULL); //incriment raster position
if(size) glDrawPixels(gm.gmBlackBoxX,gm.gmBlackBoxY, GL_RGBA, GL_UNSIGNED_BYTE, RGBData);
glBitmap (0,0,0,0,(GLfloat)-gm.gmptGlyphOrigin.x,-((GLfloat)gm.gmptGlyphOrigin.y-(GLfloat)gm.gmBlackBoxY),NULL); //incriment raster position
glBitmap (0,0,0,0,(GLfloat)gm.gmCellIncX,(GLfloat)gm.gmCell IncY,NULL); //incriment raster position

glDisable (GL_BLEND);


delete []data;
delete []RGBData;

glPixelStorei (GL_UNPACK_ALIGNMENT,1);

return TRUE;