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 = (FT_BitmapGlyphRec) *charGlyph_bitmap;*/
currentCharTex = &face->textures;
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;
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.