Sign in to follow this  
NeuralCrack

Freetype char misalignment problems

Recommended Posts

NeuralCrack    122
Hi, --------------background info... skip it if you want------------ First I hesitated about implementing a FreeType engine into my program, and meanwhile I used WGL fonts. Then I thinked: "Hey, it will be good to make the game plattform-independent, so why not to use FreeType?". So I got to work. First I tried to make my way through using the Nehe's FreeType tutorial... Didn't understand it, so I abandoned. Later I tried again, and finally I went up with something that makes sense. ---------------------------------------------------------------- But now I meet a problem: it works well, but the characters are misaligned! I tried all I could, but I couldn't fix it. Could anyone of you take a look at this code and help me to fix the problem? Here is the code of my FreeType library:
/* freetype_lib.c
 * Copyright (C) 2004 NeuralCrack
 */
 
#include <ft2build.h>
#include <freetype/freetype.h>
#include <freetype/ftglyph.h>

/* enum declaration */
typedef enum {
	ftlib_fontFace_regular,
	ftlib_fontFace_bold,
	ftlib_fontFace_italic,
	ftlib_fontFace_boldItalic
} ftlib_fontFaceStyles;

/* struct declaration */
typedef struct {
	FT_Face freetypeFace;
	glTexture textures[255];		/* one for each glyph in the face */
	int height, displayListBase;
} ftlib_fontFace;

typedef struct {
	ftlib_fontFace faces[4];		/* see 'ftlib_fontFaceStyles' enum */
	int height;
} ftlib_font;

/* variable declaration */
char				ftlib_fontPath[255];
FT_Library		ftlib_mainLibrary;

/* function prototypes */
void		ftlib_init(char*, FT_Library*);
void		ftlib_shutdown(FT_Library);
void		ftlib_loadFontFace(char*, int, ftlib_fontFace*, FT_Library);
void		ftlib_print(ftlib_fontFace, unsigned int, unsigned int, char*, ...);

/* function implementations */
void ftlib_init(char fontPath[], FT_Library *lib)
{
	strcpy(ftlib_fontPath, fontPath);
	FT_Init_FreeType(lib);
}

void ftlib_shutdown(FT_Library lib)
{
	FT_Done_FreeType(lib);
	return;
}

void ftlib_loadFontFace(char facePath[], int height, ftlib_fontFace *face, FT_Library lib)
{
	int i, x, y;
	float x2, y2;
	FT_Glyph charGlyph;
	FT_BitmapGlyph charGlyph_bitmap;
	glTexture *currentCharTex;
	
	FT_New_Face(lib, facePath, 0, &face->freetypeFace);
	FT_Set_Char_Size(face->freetypeFace, (height*64), (height*64), 96,96);
	face->height = height;
	face->displayListBase = glGenLists(255);
	
	for(i=0; i<255; i++) {			/* now load all the glyphs inside the given face */
		/* get all the data from FreeType */
		FT_Load_Glyph(face->freetypeFace, FT_Get_Char_Index(face->freetypeFace, i), FT_LOAD_DEFAULT);
		FT_Get_Glyph(face->freetypeFace->glyph, &charGlyph);
		FT_Glyph_To_Bitmap(&charGlyph, FT_RENDER_MODE_NORMAL, 0, true);
		charGlyph_bitmap = (FT_BitmapGlyph) charGlyph;
		
		/* quick access and some cleaning */
		/*face->freetypeBitmapGlyphs[i] = (FT_BitmapGlyphRec) *charGlyph_bitmap;*/
		currentCharTex = &face->textures[i];
		memset(currentCharTex, 0, sizeof(glTexture));
		
		/* now create a texture with the values FreeType gave to us */
		currentCharTex->width = math_nextp2(charGlyph_bitmap->bitmap.width);	
		currentCharTex->height = math_nextp2(charGlyph_bitmap->bitmap.rows);
		currentCharTex->bpp = 8;	currentCharTex->pixelFormat = GL_RGBA;	currentCharTex->pfBytes_count = 4;
		currentCharTex->data = (unsigned char *) malloc(2*currentCharTex->width*currentCharTex->height);
		
		/* hey, don't ask, this works :) */
		for(y=0; y<(currentCharTex->height); y++) {
			for(x=0; x<(currentCharTex->width); x++) {
				currentCharTex->data[2*(x+y*currentCharTex->width)] = currentCharTex->data[2*(x+y*currentCharTex->width)+1] =
				(x>=charGlyph_bitmap->bitmap.width) || (y>=charGlyph_bitmap->bitmap.rows) ? 0 : charGlyph_bitmap->bitmap.buffer[x+charGlyph_bitmap->bitmap.width*y];
			}
		}
		/* ... */
		glGenTextures(1, ¤tCharTex->glID);
		glBindTexture(GL_TEXTURE_2D, currentCharTex->glID);
		glTexImage2D(GL_TEXTURE_2D, 0, currentCharTex->pfBytes_count, currentCharTex->width, currentCharTex->height, 0, 
								GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, currentCharTex->data);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
								
		/* now we create the display list with the textured quad inside */
		glNewList( (face->displayListBase+i), GL_COMPILE);
			glBindTexture(GL_TEXTURE_2D, currentCharTex->glID);
			glBegin(GL_QUADS);
				glTexCoord2f(0,y2);		glVertex2f(0, charGlyph_bitmap->bitmap.rows);		/* down left */
				glTexCoord2f(0,0);	     glVertex2f(0,0);															/* up left */
				glTexCoord2f(x2,0);     glVertex2f(charGlyph_bitmap->bitmap.width, 0);	/* up right */
				glTexCoord2f(x2,y2);   glVertex2f(charGlyph_bitmap->bitmap.width, charGlyph_bitmap->bitmap.rows);		/* down right */
			glEnd();
		glEndList(); 
		
		/* ok, now it's all done... */
	}
	return;
}

void ftlib_print(ftlib_fontFace face, unsigned int x, unsigned int y, char *fmt, ...)
{
	int charCode, i;
	char text[255];
	va_list ap;
	
	va_start(ap, fmt);
		vsprintf(text, fmt, ap);
	va_end(ap);
	
	glLoadIdentity();
	glTranslatef(x,y,0);
	
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		
	for(i=0; i<strlen(text); i++) {
		charCode = text[i];
		glCallList(face.displayListBase+charCode);
		glTranslatef(face.textures[charCode].width,0,0);
	 }
	 
	glDisable(GL_BLEND);
	glDisable(GL_TEXTURE_2D); 
}



And here's the definition of glTexture:
typedef struct {
	unsigned int width, height, bpp;
	unsigned int pixelFormat, pfBytes_count;
	unsigned int glID;
	unsigned char *data;
} glTexture;


Thanks in advance.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this