Jump to content
  • Advertisement
Sign in to follow this  

OpenGL SDL_TTF with OpenGL

This topic is 3896 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

Here is the finished code for my SDL_TTF wrapper class for use with OpenGL. Upon loading a TTF file, it renders every glyph to a 1024x1024 temporary texture, and renders glyphs using texture coords. You will have to implement the SDL_Surface_To_GL_Tex() yourself, since the code I'm using is from elsewhere. It has been testing on linux, simply remove any Windows specific headers. Screenshot: Header:
#ifndef __SYM_FONT
#define __SYM_FONT

#include <windows.h>

#include <GL/gl.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>

#include <string>
#include <vector>

#include "SYM_3DMaths.h"
#include "SYM_SDL_GL_Utils.h"

using namespace std;

namespace SYM
	//Converts an SDL surface into a GLuint
	GLuint SDL_Surface_To_GL_Tex(SDL_Surface *Surface);

	class SYM_GLYPH
			//Glyph attributes
			int MinX, MaxX, MinY, MaxY, Advance;

			//Texture coordinates
			SYM_UVCOORD TexCoords[2];

	class SYM_FONT


			//Load TTF font and process into a glyph sheet
			bool LoadTTFFont(string TTF_Filename, int Size);

			//Render text
			void RenderText(string Text, float x, float y);

			//Calculates width of text
			float GetTextWidth(string Text);

			//Set text colour
			void SetColour(int r, int g, int b);

			//Vector of glyphs
			vector<SYM_GLYPH> Glyphs;

			//Temporary glyph
			SYM_GLYPH *TempGlyph;

			//The texture sheet containing the glyphs
			GLuint GlyphSheet;

			//Temporary SDL surface for loading glyphs
			SDL_Surface *TempGlyphSurface;

			//Temporary SDL surface for the glyph sheet
			SDL_Surface *TempGlyphSheet;

			//TTF font
			TTF_Font* Font;

			//Font attributes
			int Height, Ascent, Descent, LineSkip;

			int ColourR, ColourG, ColourB;

			//Current position on the glyph sheet
			SDL_Rect CurrentPos;

			//Size of current glyph
			SDL_Rect GlyphRect;

} //Namespace


#include <algorithm>

#include "SYM_Font.h"
#include "SYM_Engine.h"

namespace SYM
		//Set default colour
		ColourR = 255;
		ColourG = 255;
		ColourB = 255;

		GlyphRect.x = 0;
		GlyphRect.y = 0;
		GlyphRect.w = 0;
		GlyphRect.h = 0;

		CurrentPos.x = 0;
		CurrentPos.y = 0;
		CurrentPos.w = 0;
		CurrentPos.h = 0;

	bool SYM_FONT::LoadTTFFont(string TTF_Filename, int Size)
		//Convert filename to upper case
		transform(TTF_Filename.begin(), TTF_Filename.end(), TTF_Filename.begin(), toupper);

		//Check if last 4 characters of string are not '.TTF'
		if ((TTF_Filename.substr(TTF_Filename.size() - 4, TTF_Filename.size()) != ".TTF"))
			//Add the extension
			TTF_Filename += ".TTF";

		//Prefix font name with path from engine config
		string FontFile = Engine->FontsPath + TTF_Filename;

		//Load the font
		Font = TTF_OpenFont(FontFile.c_str(), Size);

		//Check font loaded
        if (Font == NULL)
			return false;

		//Get font attributes
		Ascent = TTF_FontAscent(Font);
        Descent = TTF_FontDescent(Font);
        Height = TTF_FontHeight(Font);
        LineSkip = TTF_FontLineSkip(Font);

		//TODO: Pre-calculate the size of the glyph sheet
		TempGlyphSheet = SDL_CreateRGBSurface(SDL_SWSURFACE, 1024, 1024, 32, 0, 0, 0, 0);

		//SDL_FillRect(TempGlyphSheet, 0, SDL_MapRGB(TempGlyphSheet->format, 255, 0, 255));

		//Loop through all chars
		for (int i = 0; i <= 254; i++)
			//Clear the surface
			TempGlyphSurface = NULL;

			//Render the glyph onto the SDL surface, in white
			SDL_Color GlyphColour = {255, 255, 255, 0};
			TempGlyphSurface = TTF_RenderGlyph_Blended(Font, i, GlyphColour);

			//New temp glyph
			TempGlyph = new SYM_GLYPH;

			//Get the glyph attributes
			TTF_GlyphMetrics(Font, i, &TempGlyph->MinX, &TempGlyph->MaxX, &TempGlyph->MinY, &TempGlyph->MaxY, &TempGlyph->Advance);

			//Set size of glyph rect
			GlyphRect.w = TempGlyphSurface->w;
			GlyphRect.h = TempGlyphSurface->h;

			//Set size of current position rect
			CurrentPos.w = CurrentPos.x + TempGlyph->MaxX;
			CurrentPos.h = CurrentPos.y +  TempGlyph->MaxY;

			//Blit the glyph onto the glyph sheet
			SDL_BlitSurface(TempGlyphSurface, &GlyphRect, TempGlyphSheet, &CurrentPos);

			//Set texture coordinates for the glyph
			TempGlyph->TexCoords[0].u = (float)CurrentPos.x / 1024;
			TempGlyph->TexCoords[0].v = 1 - ((float)CurrentPos.y / 1024);

			TempGlyph->TexCoords[1].u = (float)(CurrentPos.x + CurrentPos.w) / 1024;
			TempGlyph->TexCoords[1].v = 1 - ((float)(CurrentPos.y + CurrentPos.h) / 1024);

			//Position xpos ready for next glyph
			CurrentPos.x += GlyphRect.w;

			//If the next character will run off the edge of the glyph sheet, advance to next row
			if (CurrentPos.x + CurrentPos.w > 1024)
				CurrentPos.x = 0;
			 	CurrentPos.y += Height;

			//Push back to glyphs vector

			//Delete temp glyph
			delete TempGlyph;

			//Free surface

		//Close the font

		//Convert the SDL glyph sheet to an OpenGL compliant texture
		GlyphSheet = SDL_Surface_To_GL_Tex(TempGlyphSheet);

		//Free the temp glyph sheet surface

		return true;

	void SYM_FONT::RenderText(string Text, float x, float y)
		int GWidth, GHeight, MinX, MaxX, MinY, MaxY, CharID;

		//Enable texture mapping

		//Bind the glyph sheet texture
        glBindTexture(GL_TEXTURE_2D, GlyphSheet);

		//Enable blending

		//Loop through characters
		for (int i = 0; i < Text.size(); i++)
			//Get ID of current char
			CharID = (int)Text;

			//Get dimentions of current char
			MinX = Glyphs[CharID].MinX;
			MaxX = Glyphs[CharID].MaxX;
			MinY = Glyphs[CharID].MinY;
			MaxY = Glyphs[CharID].MaxY;

			//Set text blend colour
			glColor3ub(ColourR, ColourG, ColourB);

			//Draw the glyph
				glTexCoord2f(Glyphs[CharID].TexCoords[0].u, Glyphs[CharID].TexCoords[1].v); glVertex2f(x + MinX, y + MinY);
				glTexCoord2f(Glyphs[CharID].TexCoords[1].u, Glyphs[CharID].TexCoords[1].v); glVertex2f(x + MaxX, y + MinY);
				glTexCoord2f(Glyphs[CharID].TexCoords[1].u, Glyphs[CharID].TexCoords[0].v); glVertex2f(x + MaxX, y + MaxY);
				glTexCoord2f(Glyphs[CharID].TexCoords[0].u, Glyphs[CharID].TexCoords[0].v); glVertex2f(x + MinX, y + MaxY);

			//Position x ready for next glyph
			x += Glyphs[CharID].Advance;

		//Disable blending

		//Disable texture mapping

	float SYM_FONT::GetTextWidth(string Text)
		int Width = 0;
		int CharID;

		for (int i = 0; i < Text.size(); i++)
			CharID = (int)Text;
			Width += Glyphs[CharID].Advance;

		return Width;

} //Namespace

Example usage:
//Don't forget to initialise SDL first

	SYM_FONT Arial24;

	//Load the font
	if (!Arial24.LoadTTFFont("arial.ttf", 24))
		cout << "Error: Could not load font\n";
		return false;

	//Set text colour to red
	Arial24.SetColour(255, 0, 0);

	//Render text
	Arial24.RenderText("Hello World!", 100, 200);

Thank you to all at Gamedev who helped me out with my problems writing it. I hope someone finds the code useful.

Share this post

Link to post
Share on other sites
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!