kaolin fire

Member
  • Content count

    1
  • Joined

  • Last visited

Community Reputation

122 Neutral

About kaolin fire

  • Rank
    Newbie
  1. 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 ### /** 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;