Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


We're also offering banner ads on our site from just $5! 1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Problem with lesson 43


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
1 reply to this topic

#1 Katz   Members   -  Reputation: 100

Like
0Likes
Like

Posted 21 June 2011 - 08:06 AM

Hello !

I'm having troubles with lesson 43. I can't get FreeType to work and display text. I made a test program to try to make it work.
I've changed some things from lesson 43, taken out some things I wouldn't need, changed some variables names to respect my own conventions, and mixed it up a little with the tutorial on FreeType's website.

Problem is I don't get any text. OpenGL works fine, as I get a red rectangle. But no text.
The main problem is I don't really understand all that was done in the tutorial, so I might have changed some stuff I wasn't supposed to... I especially cut a whole lot in the "print()" function (renamed "write()" in my code).

Can someone help me get this code to work? Or point out at least what vital part I'm missing, so I can look it up in the tutorial?

Thanks !

Code follows:
#include <SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include <vector>
#include <string>
#include <iostream>

using namespace std;

struct font_data
{
	int h;
	GLuint *textures;
	GLuint listBase;

	void init(string fontName, unsigned int h); //create font of required height
	void clean();                       		//clean font data
};

void write(const font_data &ft_font, int x, int y, string text);

//get power of two right above given number
inline int nextP2(int nb)
{
	int ret=1;
	while(ret < nb)
    	ret *= 2;
	return ret;
}

//create a display lit corresponding to the given character
void makeDList(FT_Face font, char ch, GLuint listBase, GLuint *texBase)
{
	if(FT_Load_Char(font, ch, FT_LOAD_RENDER))
    	cout << "FT_Load_Char failed in makeDList." <<  endl;
	FT_Bitmap &bitmap = font->glyph->bitmap;

	//get required with and height to get correct texture size
	int width = nextP2(bitmap.width);
	int height = nextP2(bitmap.rows);

	GLubyte *expandedData = new GLubyte [2*width*height];

	for(int j=0;j<height;j++)
	{
    	for(int i=0;i<width;i++)
        	expandedData[2*(i+j*width)] = expandedData[2*(i+j*width)+1] = (i>=bitmap.width || j>=bitmap.rows) ? 0 : bitmap.buffer[i+bitmap.width*j];
	}

	glBindTexture(GL_TEXTURE_2D, texBase[ch]);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expandedData);

	delete [] expandedData;

	glNewList(listBase + ch, GL_COMPILE);

	glBindTexture(GL_TEXTURE_2D, texBase[ch]);

	glPushMatrix();

	//glTranslatef(font->glyph->left,0,0); //shift character to have right amount of space before
	//glTranslatef(0,font->glyph->top -  bitmap.rows,0); //move down a little if previous line has lower character
	int x = bitmap.width / width; //take empty space around char into account
	int y = bitmap.rows / height;

	glBegin(GL_QUADS);
	glTexCoord2d(0,0);
    	glVertex2f(0,bitmap.rows);
	glTexCoord2d(0,y);
    	glVertex2f(0,0);
	glTexCoord2d(x,y);
    	glVertex2f(bitmap.width,0);
	glTexCoord2d(x,0);
    	glVertex2f(bitmap.width,bitmap.rows);
	glEnd();
	glPopMatrix();
	//glTranslatef(font->glyph->advance.x * 64,0,0);

	glEndList();
}

void font_data::init(string fontName, unsigned int h)
{
	textures = new GLuint[128];
	this->h=h;

	FT_Library library;
	if(FT_Init_FreeType(&library))
    	cout << "Could not initialize Freetype library" << endl;

	FT_Face font;
	if(FT_New_Face(library, fontName.c_str(), 0, &font))
    	cout << "Could not open  font \"" <<fontName<<"\"."<<endl;
	FT_Set_Char_Size(font, h*64,h*64,96,96); //set font size

	//allocate resources for textures and display lists
	listBase=glGenLists(128);
	glGenTextures(128,textures);

	//create each of the fonts display lists
	for(unsigned char i=0;i<128;i++)
    	makeDList(font,i,listBase,textures);

	FT_Done_Face(font);
	FT_Done_FreeType(library);
}

void font_data::clean()
{
	glDeleteLists(listBase,128);
	glDeleteTextures(128,textures);
	delete [] textures;
}

void write(const font_data &ft_font, int x, int y, string text)
{
	GLuint font = ft_font.listBase;
	glListBase(font);

	glPushMatrix();
	glLoadIdentity();
	glTranslatef(x,y,0); //move to text
	glCallLists(text.length(), GL_UNSIGNED_BYTE,text.c_str());
	glPopMatrix();
}

int main ( int argc, char** argv )
{
	SDL_Init( SDL_INIT_VIDEO );
	SDL_SetVideoMode(800, 600, 32, SDL_OPENGL);
	//initialize freetype
	/*FT_Library freetype;
	if(FT_Init_FreeType(&freetype) != 0)
	{
    	cout << "Unable to initialize Freetype library." <<endl;
    	exit(EXIT_FAILURE);
	}*/
	//set openGL parameters
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0,800,600,0);
	glDisable(GL_DEPTH_TEST); //depth buffering
	glEnable(GL_TEXTURE_2D); //texture using
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

	font_data myFont;
	myFont.init("../TD/fonts/jester.ttf", 40);

	SDL_Event event;
	bool quit = false;
	while(!quit)
	{
    	glClear(GL_COLOR_BUFFER_BIT);

    	glColor3ub(255,0,0);
    	glDisable(GL_TEXTURE_2D);
    	glBegin(GL_QUADS);
        	glVertex2d(180,280);
        	glVertex2d(480,280);
        	glVertex2d(480,480);
        	glVertex2d(180,480);
    	glEnd();
    	glColor3ub(0,255,0);
    	glEnable(GL_TEXTURE_2D);
    	write(myFont,200,300, "Hello World!");

    	glFlush();
    	SDL_GL_SwapBuffers();

    	while (SDL_PollEvent(&event))
    	{
        	if(event.type == SDL_QUIT || (event.type == SDL_KEYDOWN && (event.key.keysym.sym == SDLK_ESCAPE || event.key.keysym.sym == SDLK_RETURN)))
            	quit=true;
    	}
	}

	myFont.clean();
	SDL_Quit();
}


Sponsor:

#2 Katz   Members   -  Reputation: 100

Like
0Likes
Like

Posted 22 June 2011 - 12:58 PM

OK, I solved my own problem, after much looking around.
I had two main problems: One was that my texture coordinates were entered into integers, although they are supposed to by smaller than 1. (Two days for this problem... *facepalm*)
The other was that I am using a different coordinate system: My ordinate axis runs from top to bottom and not bottom to top.

Anyway, working code, if it may help anybody:
#include <SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include <vector>
#include <string>
#include <iostream>

using namespace std;

struct font_data
{
	int h;
	GLuint *textures;
	GLuint listBase;

	void init(string fontName, unsigned int h); //create font of required height
	void clean();                           	//clean font data
};

void write(const font_data &ft_font, int x, int y, string text);

//get power of two right above given number
inline int nextP2(int nb)
{
	int ret=1;
	while(ret < nb)
    	ret *= 2;
	return ret;
}

//create a display lit corresponding to the given character
void makeDList(FT_Face font, unsigned char ch, GLuint listBase, GLuint *texBase)
{
	if(FT_Load_Char(font, ch, FT_LOAD_RENDER))
    	cout << "FT_Load_Char failed in makeDList." <<  endl;
	FT_GlyphSlot glyph = font->glyph;
	FT_Bitmap &bitmap = glyph->bitmap;

	//get required width and height to get correct texture size
	int width = nextP2(bitmap.width);
	int height = nextP2(bitmap.rows);

	GLubyte *expandedData = new GLubyte [2*width*height];

	for(int j=0;j<height;j++)
	{
    	for(int i=0;i<width;i++)
    	{
        	expandedData[2*(i+j*width)] = 255;
        	expandedData[2*(i+j*width)+1] = (i>=bitmap.width || j>=bitmap.rows) ? 0 : bitmap.buffer[i+bitmap.width*j];
    	}
	}

	glBindTexture(GL_TEXTURE_2D, texBase[ch]);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expandedData);

	delete [] expandedData;

	glNewList(listBase + ch, GL_COMPILE);

    	glBindTexture(GL_TEXTURE_2D, texBase[ch]);

    	glPushMatrix();
    	glTranslatef(glyph->bitmap_left,0,0); //shift character to have right amount of space before
    	glTranslatef(0, (font->bbox.yMax - glyph->metrics.horiBearingY)/64,0); //move down a little if previous line has lower character
    	double x = (double)bitmap.width /(double)width; //take empty space around char into account
    	double y = (double)bitmap.rows / (double)height;

    	glBegin(GL_QUADS);
    	glTexCoord2d(0,y);
        	glVertex2f(0,bitmap.rows);
    	glTexCoord2d(0,0);
        	glVertex2f(0,0);
    	glTexCoord2d(x,0);
        	glVertex2f(bitmap.width,0);
    	glTexCoord2d(x,y);
        	glVertex2f(bitmap.width,bitmap.rows);
    	glEnd();
    	glPopMatrix();
    	glTranslatef(glyph->metrics.horiAdvance/64,0,0);

	glEndList();
}

void font_data::init(string fontName, unsigned int h)
{
	textures = new GLuint[128];
	this->h=h;

	FT_Library library;
	if(FT_Init_FreeType(&library))
    	cout << "Could not initialize Freetype library" << endl;

	FT_Face font;
	if(FT_New_Face(library, fontName.c_str(), 0, &font))
    	cout << "Could not open  font \"" <<fontName<<"\"."<<endl;
	FT_Set_Char_Size(font, h*64,h*64,96,96); //set font size

	//allocate resources for textures and display lists
	listBase=glGenLists(128);
	glGenTextures(128,textures);

	//create each of the fonts display lists
	for(unsigned char i=0;i<128;i++)
    	makeDList(font,i,listBase,textures);

	FT_Done_Face(font);
	FT_Done_FreeType(library);
}

void font_data::clean()
{
	glDeleteLists(listBase,128);
	glDeleteTextures(128,textures);
	delete [] textures;
}

void write(const font_data &ft_font, int x, int y, string text)
{
	GLuint font = ft_font.listBase;
	glListBase(font);

	glPushMatrix();
	glTranslatef(x,y,0); //move to text
	glCallLists(text.length(), GL_UNSIGNED_BYTE,text.c_str());
	glPopMatrix();
}

int main ( int argc, char** argv )
{
	SDL_Init( SDL_INIT_VIDEO );
	SDL_SetVideoMode(800, 600, 32, SDL_OPENGL);
	//set openGL parameters
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0,800,600,0);
	glDisable(GL_DEPTH_TEST); //depth buffering
	glEnable(GL_TEXTURE_2D); //texture using
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

	font_data myFont;
	myFont.init("../TD/fonts/jester.ttf", 20);

	SDL_Event event;
	bool quit = false;
	while(!quit)
	{
    	glClear(GL_COLOR_BUFFER_BIT);

    	glColor3ub(255,255,255);
    	glDisable(GL_TEXTURE_2D);
    	glBegin(GL_QUADS);
        	glVertex2d(0,0);
        	glVertex2d(800,0);
        	glVertex2d(800,600);
        	glVertex2d(0,600);
    	glEnd();
    	glEnable(GL_TEXTURE_2D);
    	glColor3ub(180,180,0);
    	write(myFont,200,300, "Hello World!");

    	glFlush();
    	SDL_GL_SwapBuffers();

    	while (SDL_PollEvent(&event))
    	{
        	if(event.type == SDL_QUIT || (event.type == SDL_KEYDOWN && (event.key.keysym.sym == SDLK_ESCAPE || event.key.keysym.sym == SDLK_RETURN)))
            	quit=true;
    	}
	}

	myFont.clean();
	SDL_Quit();
}





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS