Thank you very much. The two things run very well!.
for reference: Using SDL_ttf with OpenGL
Started by C-Junkie, Nov 22 2004 11:46 AM
25 replies to this topic
Sponsor:
#22 Members - Reputation: 122
Posted 20 June 2006 - 10:58 PM
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 ###
###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[i].pic = NULL;
glyphs[i].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;
#24 Anonymous Poster_Anonymous Poster_* Guests - Reputation:
Posted 17 January 2007 - 07:12 AM
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 "é" "ê" "à" ?
#25 Members - Reputation: 122
Posted 04 August 2008 - 10:50 PM
@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.
#26 Members - Reputation: 100
Posted 28 February 2011 - 07:22 AM
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






