Jump to content
  • Advertisement
Sign in to follow this  
Starfox

OpenGL FreeType2 Trouble

This topic is 2561 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've been trying to replace the font rendering engine I'm using that someone else wrote with one of my own (for licensing reasons) based on FreeType 2. I wrote a simple app to test string-to-GL-texture rendering, but I'm seeing corruption in some characters and I've been trying to pin point the problem with no luck so far. I think I might need a second pair of eyes with more FreeType2 experience if possible - my code is based entirely on the FreeType2 first tutorial sample. Here's what the rendering looks like:

Picture


(This is supposed to be "ABCDE".)

and here's the code:


#include <cassert>

#include <iostream>

#include <algorithm>

using std::max;

#ifdef _WIN32
#include <GL/glut.h>
#endif

#if defined(__APPLE__) && defined(__MACH__)
#include <OpenGL/OpenGL.h>
#include <GLUT/glut.h>
#endif

#include <ft2build.h>
#include FT_FREETYPE_H

#include <stdio.h>
#include <string.h>
#include <math.h>

#include <ft2build.h>
#include FT_FREETYPE_H

GLuint Texture;
float ScreenWidth = 1280;
float ScreenHeight = 720;
float TextWidth;
float TextHeight;

void display()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, ScreenWidth - 1, 0, ScreenHeight - 1, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
const int OffsetX = 100;
const int OffsetY = 100;
glTranslatef(OffsetX, OffsetY, 0);
const float Scale = 4.0;
glScalef(Scale, Scale, Scale);
glClearColor(0, 1, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, Texture);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST );
// when texture area is large, bilinear filter the original
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBegin(GL_QUADS);
glColor3f(1, 0, 0);
glTexCoord2f(0.0, 0.0);
glVertex3f(-0, -0, 0);
glTexCoord2f(0.0, 1.0);
glVertex3f(-0, TextHeight, 0);
glTexCoord2f(1.0, 1.0);
glVertex3f(TextWidth, TextHeight, 0);
glTexCoord2f(1.0, 0.0);
glVertex3f(TextWidth, -0, 0);
glEnd();
glutSwapBuffers();
}

void idle()
{
glutPostRedisplay();
}

struct int2
{
int x;
int y;
};

struct extents
{
int2 size;
int2 offset;
};

extents text_extents(const char* const Text, FT_Face& Face)
{
FT_GlyphSlot Slot = Face->glyph;
extents Result;
Result.size.x = Result.size.y = 0;
Result.offset.x = Result.offset.y = 0;
int num_chars = strlen(Text);
FT_Vector pen;
FT_Error error;
pen.x = pen.y = 0;
long MaximumHeight = 0;
for (int n = 0; n < num_chars; n++ )
{
/* load glyph image into the slot (erase previous one) */
error = FT_Load_Char( Face, Text[n], FT_LOAD_RENDER );
if ( error )
continue; /* ignore errors */
//
FT_Glyph_Metrics Metrics = Slot->metrics;
MaximumHeight = max(MaximumHeight, Metrics.height / 64);
Result.size.x += (Metrics.horiAdvance / 64);
}
Result.size.y = MaximumHeight;
return Result;
}

int main (int argc, const char * argv[])
{

// insert code here...
std::cout << "Hello, World!\n";
int x = 1;
char* y = "dummy";
glutInit(&x, &y);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(1280, 720);
glutInitWindowPosition(100,100);
glutCreateWindow("FreeType2");
glutDisplayFunc(display);
glutIdleFunc(idle);
//
FT_Library library;
FT_Face face;

FT_GlyphSlot slot;
FT_Matrix matrix; /* transformation matrix */
FT_UInt glyph_index;
FT_Vector pen; /* untransformed origin */
FT_Error error;

char* filename;
char* text;

double angle;
int target_height;
int n, num_chars;

filename = "font.ttf"; /* first argument */
text = "ABCDE"; /* second argument */
num_chars = strlen( text );
angle = ( 180.0 / 360.0 ) * 3.14159 * 2.0; /* use 25 degrees */

error = FT_Init_FreeType( &library ); /* initialize library */
/* error handling omitted */
using namespace std;

error = FT_New_Face( library, filename, 0, &face ); /* create face object */
/* error handling omitted */

/* use 50pt at 100dpi */
error = FT_Set_Char_Size( face, 50 * 64, 50 * 64,
100, 0 ); /* set character size */
/* error handling omitted */

slot = face->glyph;

/* set up matrix */
matrix.xx = (FT_Fixed) 1.0 * 0x10000L;
matrix.xy = 0;
matrix.yx = 0;
matrix.yy = (FT_Fixed) -1.0 * 0x10000L;
//
int2 CalcSize = text_extents(text, face).size;
TextWidth = CalcSize.x;
TextHeight = CalcSize.y;
cout << "String " << text << " W: " << TextWidth << " H: " << TextHeight << endl;
glGenTextures(1, &Texture);
glBindTexture(GL_TEXTURE_2D, Texture);
unsigned char* ClearData = new unsigned char [CalcSize.x * CalcSize.y];
std::fill(ClearData, ClearData + (CalcSize.x * CalcSize.y), 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, CalcSize.x, CalcSize.y, 0, GL_ALPHA, GL_UNSIGNED_BYTE, ClearData);
delete [] ClearData;
GLuint GLError = glGetError();
if(GLError != GL_NO_ERROR)
{
cout << "GL Error: " << GLError << endl;
}
//
pen.x = pen.y = 0;
int2 Offset;
Offset.x = Offset.y = 0;
FT_Set_Transform( face, &matrix, &pen );
for ( n = 0; n < num_chars; n++ )
{
/* load glyph image into the slot (erase previous one) */
error = FT_Load_Char( face, text[n], FT_LOAD_RENDER );
if ( error )
{
cout << "Load char error!\n";
continue; /* ignore errors */
}
//
unsigned int height = slot->bitmap.rows;
unsigned int width = slot->bitmap.width;
void* data = (slot->bitmap.buffer);
cout << "Upload - offset X: " << Offset.x << " offset Y: " << Offset.y << endl;
cout << "Upload - Width : " << width << " Height : " << height << endl;
glTexSubImage2D(GL_TEXTURE_2D, 0, Offset.x, Offset.y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, data);
Offset.x += (slot->metrics.horiAdvance / 64);
//
cout << "Char: " << text[n] << " W: " << width << " H: " << height << endl;
cout << "Pitch: " << slot->bitmap.pitch << endl;
cout << "Expected Pitch: " << (width) << endl;
if((slot->bitmap.pitch) != width)
{
cout << "!!! ERROR: Pitches don't match nominal value!\n";
}
cout << "*****\n";
//

/* increment pen position */
pen.x += slot->advance.x;
pen.y += slot->advance.y;
}
//
FT_Done_Face ( face );
FT_Done_FreeType( library );
glutMainLoop();
return 0;
}



Any ideas?

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!