for reference: Using SDL_ttf with OpenGL
I've been tinkering with Bob Pendleton's SDL_ttf font class and made it support newlines... I also took out a few things that I wasn't using, do forgive... it should be pretty obvious how to mix/match :) [[and I split it into the .h and .cpp, and took out the 'background color', instead using alpha blending, and... not sure what else, TBH, sorry]]
### font.h ###
/**
+--------------------------------------+
+ Bob Pendleton: writer and programmer +
+ email: Bob@xxxxxxxxxxxxx +
+ blog: www.Stonewolf.net +
+ web: www.GameProgrammer.com +
+--------------------------------------+
http://www.oreillynet.com/pub/au/1205
Edits by Kaolin Fire ( kfire@xxxxxxxx; web: erif.org )
now takes into account glyph minx so glyphs can overlap as intended
now takes into account newline character
**/
class Font
{
private:
static const int minGlyph = ' ';
static const int maxGlyph = 126;
static int initCounter;
typedef struct
{
int minx, maxx;
int miny, maxy;
int advance;
SDL_Surface *pic;
GLuint tex;
GLfloat texMinX, texMinY;
GLfloat texMaxX, texMaxY;
} glyph;
int height;
int ascent;
int descent;
int lineSkip;
glyph glyphs[maxGlyph + 1];
const char *fontName;
int pointSize;
float fgRed, fgGreen, fgBlue;
TTF_Font *ttfFont;
SDL_Color foreground;
void loadChar(char c);
public:
Font(const char *fontName,
int pointSize,
float fgRed, float fgGreen, float fgBlue);
~Font();
void initFont();
int getLineSkip();
int getHeight();
void textSize(char *text, SDL_Rect *r);
void drawText(char *text, int x, int y);
};
###font.cpp###
### font.h ###
/** BTW, it is covered by the LGPL ** Bob Pendleton **//** http://www.devolution.com/pipermail/sdl/2004-December/066119.html **/
/**
+--------------------------------------+
+ Bob Pendleton: writer and programmer +
+ email: Bob@xxxxxxxxxxxxx +
+ blog: www.Stonewolf.net +
+ web: www.GameProgrammer.com +
+--------------------------------------+
http://www.oreillynet.com/pub/au/1205
Edits by Kaolin Fire ( kfire@xxxxxxxx; web: erif.org )
now takes into account glyph minx so glyphs can overlap as intended
now takes into account newline character
**/
class Font
{
private:
static const int minGlyph = ' ';
static const int maxGlyph = 126;
static int initCounter;
typedef struct
{
int minx, maxx;
int miny, maxy;
int advance;
SDL_Surface *pic;
GLuint tex;
GLfloat texMinX, texMinY;
GLfloat texMaxX, texMaxY;
} glyph;
int height;
int ascent;
int descent;
int lineSkip;
glyph glyphs[maxGlyph + 1];
const char *fontName;
int pointSize;
float fgRed, fgGreen, fgBlue;
TTF_Font *ttfFont;
SDL_Color foreground;
void loadChar(char c);
public:
Font(const char *fontName,
int pointSize,
float fgRed, float fgGreen, float fgBlue);
~Font();
void initFont();
int getLineSkip();
int getHeight();
void textSize(char *text, SDL_Rect *r);
void drawText(char *text, int x, int y);
};
###font.cpp###
#include "font.h" void Font::loadChar(char c) { GLfloat texcoord[4]; char letter[2] = {0, 0}; if ((minGlyph <= c) && (c <= maxGlyph) && (NULL == glyphs[((int)c)].pic)) { SDL_Surface *g0 = NULL; SDL_Surface *g1 = NULL; letter[0] = c; TTF_GlyphMetrics(ttfFont, (Uint16)c, &glyphs[((int)c)].minx, &glyphs[((int)c)].maxx, &glyphs[((int)c)].miny, &glyphs[((int)c)].maxy, &glyphs[((int)c)].advance); g0 = TTF_RenderText_Blended(ttfFont, letter, foreground); if (NULL != g0) { g1 = SDL_DisplayFormatAlpha(g0); SDL_FreeSurface(g0); } if (NULL != g1) { glyphs[((int)c)].pic = g1; glyphs[((int)c)].tex = SDL_GL_LoadTexture(g1, texcoord); glyphs[((int)c)].texMinX = texcoord[0]; glyphs[((int)c)].texMinY = texcoord[1]; glyphs[((int)c)].texMaxX = texcoord[2]; glyphs[((int)c)].texMaxY = texcoord[3]; } } } Font::Font(const char *fontName, int pointSize, float fgRed, float fgGreen, float fgBlue): fontName(fontName), pointSize(pointSize), fgRed(fgRed), fgGreen(fgGreen), fgBlue(fgBlue), ttfFont(NULL) { if (0 == initCounter) { if (TTF_Init() < 0) { //TODO :: errorExit("Can't init SDL_ttf");printf("Can't init sdl_ttf !?\n"); } } initCounter++; initFont(); } Font::~Font() { initCounter--; if (0 == initCounter) { TTF_Quit(); } } void Font::initFont() { int i; ttfFont = TTF_OpenFont(fontName, pointSize); if (NULL == ttfFont) {printf("Can't open font file\n"); //TODO :: errorExit("Can't open font file"); } foreground.r = (Uint8)(255 * fgRed); foreground.g = (Uint8)(255 * fgGreen); foreground.b = (Uint8)(255 * fgBlue); height = TTF_FontHeight(ttfFont); ascent = TTF_FontAscent(ttfFont); descent = TTF_FontDescent(ttfFont); lineSkip = TTF_FontLineSkip(ttfFont); for (i = minGlyph; i <= maxGlyph; i++) { glyphs.pic = NULL; glyphs.tex = 0; } } int Font::getLineSkip() { return lineSkip; } int Font::getHeight() { return height; } void Font::textSize(char *text, SDL_Rect *r) { int maxx = 0; int advance = 0; int minx = 0; int w_largest = 0; char lastchar = 0; r->x = 0; r->y = 0; r->w = 0; r->h = height; while (0 != *text) { if ((minGlyph <= *text) && (*text <= maxGlyph)) { lastchar = *text; if (*text == '\n') { r->h += lineSkip; r->w = r->w - advance + maxx; if (r->w > w_largest) w_largest = r->w; r->w = 0; } else { loadChar(*text); maxx = glyphs[((int)*text)].maxx; advance = glyphs[((int)*text)].advance; r->w += advance; } } text++; } if (lastchar != '\n') { r->w = r->w - advance + maxx; if (r->w > w_largest) w_largest = r->w; } else { r->h -= lineSkip; } if (w_largest > r->w) r->w = w_largest; } void Font::drawText(char *text, int x, int y) { GLfloat left, right; GLfloat top, bottom; GLfloat texMinX, texMinY; GLfloat texMaxX, texMaxY; GLfloat minx; GLfloat baseleft = x; glPushAttrib(GL_ALL_ATTRIB_BITS); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); while (0 != *text) { if (*text == '\n') { x = baseleft; y += lineSkip; } else if ((minGlyph <= *text) && (*text <= maxGlyph)) { loadChar(*text); texMinX = glyphs[((int)*text)].texMinX; texMinY = glyphs[((int)*text)].texMinY; texMaxX = glyphs[((int)*text)].texMaxX; texMaxY = glyphs[((int)*text)].texMaxY; minx = glyphs[((int)*text)].minx; left = x + minx; right = x + glyphs[((int)*text)].pic->w + minx; top = y; bottom = y + glyphs[((int)*text)].pic->h; glBindTexture(GL_TEXTURE_2D, glyphs[((int)*text)].tex); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(texMinX, texMinY); glVertex2f( left, top); glTexCoord2f(texMaxX, texMinY); glVertex2f(right, top); glTexCoord2f(texMinX, texMaxY); glVertex2f( left, bottom); glTexCoord2f(texMaxX, texMaxY); glVertex2f(right, bottom); glEnd(); x += glyphs[((int)*text)].advance; } text++; } glPopAttrib(); } int Font::initCounter = 0;
Hi,
Sorry for the UP but I want to know how to use this code with Latin specials chars like "é" "ê" "à" ?
Sorry for the UP but I want to know how to use this code with Latin specials chars like "é" "ê" "à" ?
@kaolin fire
function Font::textSize is not handling newlines properly.
The first condition in the while loop should be corrected to something like:
if (((minGlyph <= *text) && (*text <= maxGlyph)) || *text == '\n')
instead of
if ((minGlyph <= *text) && (*text <= maxGlyph))
Otherwise '\n' won't be processed.
function Font::textSize is not handling newlines properly.
The first condition in the while loop should be corrected to something like:
if (((minGlyph <= *text) && (*text <= maxGlyph)) || *text == '\n')
instead of
if ((minGlyph <= *text) && (*text <= maxGlyph))
Otherwise '\n' won't be processed.
Thank you, that works instantly! I just called RenderText_Blended and (when I passed it into my gl texture creation function) it just returned a texture all of the colour passed into the TTF function.
Also Koshmaar thanks for the management system, saved me a lot of time
Also Koshmaar thanks for the management system, saved me a lot of time
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement