[gameprogrammer] Re: SDL_ttf and OpenGL

I would never have thought of doing that.
My knowledge of both SDL and OpenGL are still rather limited.


From: Bob Pendleton <bob@xxxxxxxxxxxxx>
Reply-To: gameprogrammer@xxxxxxxxxxxxx
To: Gameprogrammer Mailing List <gameprogrammer@xxxxxxxxxxxxx>
Subject: [gameprogrammer] Re: SDL_ttf and OpenGL
Date: Thu, 29 Apr 2004 09:48:39 -0500

On Thu, 2004-04-29 at 07:22, Kevin Fields wrote:
 > Hey people,
 >
 > I'm having an issue with trying to get SDL_ttf to work with OpenGL.
 > I've posted on the SDL mailing list, but I'm still not sure how I can go
 > about getting SDL_ttf to render to the screen.
 >
 > One method I was told to use was to take the surface generated by
 > TTF_RenderText_*() and make a texture out of it, then applying that 
texture
 > to a quad (or triangle strip) and rendering to the screen. When I tried
 > that, nothing appeared.
 >
 > Has anyone been able to get fonts working with SDL and OpenGL?

I've been so involved in this list (my list) for the last few days that
I have not been looking at the SDL list and missed you question. I have
indeed gotten SDL_ttf to work with OpenGL. It isn't difficult. Here is
some code that I use for the job:

//-------------------------------------------------

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];

   unsigned char *address;
   int length;
   int pointSize;
   int style;
   float fgRed, fgGreen, fgBlue;
   float bgRed, bgGreen, bgBlue;

   TTF_Font *ttfFont;

   SDL_Color foreground;
   SDL_Color background;

   void loadChar(char c)
   {
     GLfloat texcoord[4];
     char letter[2] = {0, 0};

     if ((minGlyph <= c) &&
         (c <= maxGlyph) &&
         (NULL == glyphs[c].pic))
     {
       SDL_Surface *g0 = NULL;
       SDL_Surface *g1 = NULL;

       letter[0] = c;

       TTF_GlyphMetrics(ttfFont,
                        (Uint16)c,
                        &glyphs[c].minx,
                        &glyphs[c].maxx,
                        &glyphs[c].miny,
                        &glyphs[c].maxy,
                        &glyphs[c].advance);

       g0 = TTF_RenderText_Shaded(ttfFont,
                                  letter,
                                  foreground,
                                  background);

       if (NULL != g0)
       {
         g1 = SDL_DisplayFormat(g0);
         SDL_FreeSurface(g0);
       }

       if (NULL != g1)
       {
         glyphs[c].pic = g1;
         glyphs[c].tex = loadTextureColorKey(g1, texcoord, 0, 0, 0);
         glyphs[c].texMinX = texcoord[0];
         glyphs[c].texMinY = texcoord[1];
         glyphs[c].texMaxX = texcoord[2];
         glyphs[c].texMaxY = texcoord[3];
       }
     }
   }

public:

   Font(unsigned char *address,
        int length,
        int pointSize,
        int style,
        float fgRed, float fgGreen, float fgBlue,
        float bgRed, float bgGreen, float bgBlue):
     address(address), length(length),
     pointSize(pointSize),
     style(style),
     fgRed(fgRed), fgGreen(fgGreen), fgBlue(fgBlue),
     bgRed(bgRed), bgGreen(bgGreen), bgBlue(bgBlue),
     ttfFont(NULL)
   {
     if (0 == initCounter)
     {
       if (TTF_Init() < 0)
       {
         errorExit("Can't init SDL_ttf");
       }
     }
     initCounter++;
     initFont();
   }

   ~Font()
   {
     initCounter--;
     if (0 == initCounter)
     {
       TTF_Quit();
     }
   }

   void initFont()
   {
     SDL_RWops *src = NULL;
     int i;

     src = SDL_RWFromMem(address, length);

     ttfFont = TTF_OpenFontRW(src, 1, pointSize);
     if (NULL == ttfFont)
     {
       errorExit("Can't open font file");
     }

     TTF_SetFontStyle(ttfFont, style);

     foreground.r = (Uint8)(255 * fgRed);
     foreground.g  = (Uint8)(255 * fgGreen);
     foreground.b = (Uint8)(255 * fgBlue);

     background.r = (Uint8)(255 * bgRed);
     background.g = (Uint8)(255 * bgGreen);
     background.b = (Uint8)(255 * bgBlue);

     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 getLineSkip()
   {
     return lineSkip;
   }

   int getHeight()
   {
     return height;
   }

   void textSize(char *text,
                 SDL_Rect *r)
   {
     int maxx = 0;
     int advance = 0;

     r->x = 0;
     r->y = 0;
     r->w = 0;
     r->h = height;

     while (0 != *text)
     {
       if ((minGlyph <= *text) && (*text <= maxGlyph))
       {
         loadChar(*text);

         maxx = glyphs[*text].maxx;
         advance = glyphs[*text].advance;
         r->w += advance;
       }

       text++;
     }

     r->w = r->w - advance + maxx;
   }

   void drawText(char *text, int x, int y)
   {
     GLfloat left, right;
     GLfloat top, bottom;
     GLfloat texMinX, texMinY;
     GLfloat texMaxX, texMaxY;

     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 ((minGlyph <= *text) && (*text <= maxGlyph))
       {
         loadChar(*text);

         texMinX = glyphs[*text].texMinX;
         texMinY = glyphs[*text].texMinY;
         texMaxX = glyphs[*text].texMaxX;
         texMaxY = glyphs[*text].texMaxY;

         left   = x;
         right  = x + glyphs[*text].pic->w;
         top    = y;
         bottom = y + glyphs[*text].pic->h;

         glBindTexture(GL_TEXTURE_2D, glyphs[*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[*text].advance;
       }

       text++;
     }

     glPopAttrib();
   }
};

//-------------------------------------------------

int Font::initCounter = 0;

                Bob Pendleton

 >
 > _________________________________________________________________
 > MSN Premium: Up to 11 personalized e-mail addresses and 2 months FREE*
 > 
http://join.msn.com/?pgmarket=en-ca&page=byoa/prem&xAPID=1994&DI=1034&SU=http://hotmail.com/enca&HL=Market_MSNIS_Taglines
 >
--
+--------------------------------------+
+ Bob Pendleton: writer and programmer +
+ email: Bob@xxxxxxxxxxxxx             +
+ blog:  www.Stonewolf.net             +
+ web:   www.GameProgrammer.com        +
+--------------------------------------+

_________________________________________________________________
http://join.msn.com/?pgmarket=en-ca&page=byoa/prem&xAPID=1994&DI=1034&SU=http://hotmail.com/enca&HL=Market_MSNIS_Taglines


Other related posts: