SDL_ttf: Proposed extension for precreated surfaces

Hello everyone,

I’ve been looking at SDL_ttf, especially with OpenGL in mind, and I’d
like to suggest (and implement) the following extension.

Until OpenGL 2.0 becomes widespread, any OpenGL texture must have a
height and a width which are a power of 2. But the SDL_Surfaces created
by the TTF_Render functions usually aren’t. So to place the text in a
texture, I’d have to create a new, power-of-2 conforming SDL_Surface,
blit the TTF-created one into it, and free the original. Or I could
create a suitable memory area and “blit” by hand.

Looking through the TTF_Render code, I noticed that the returned surface
is created close to the beginning of the function’s body. So it should
be possible to create functions, e.g. TTF_RenderText_Blended_WithSurface
which takes a pre-existing surface and uses it for rendering (or returns
an error if it’s too small). The current TTF_Render functions could then
be wrappers around these new functions, creating and freeing surfaces as
needed.

This could also be useful if one wanted to render a lot of text of
similar size: one could reuse a surface of sufficient size and skip a
lot of memory allocation.

Some questions:

Has this already been tried? Thought of? Discarded?

Would it be worth it, speedwise? Or is text rendering itself far slower
than the additional allocation (twice) and blitting?

Would it make sense to add positional offset parameters to the new
functions? Is this more trouble than it’s worth?

Is there an already existing better solution to the text-to-texture
thing? What do other people do?

Thanks for your time,
Benjamin

Until OpenGL 2.0 becomes widespread, any OpenGL texture must have a height
and a width which are a power of 2. But the SDL_Surfaces created by the
TTF_Render functions usually aren’t. So to place the text in a texture, I’d
have to create a new, power-of-2 conforming SDL_Surface, blit the TTF-created
one into it, and free the original. Or I could create a suitable memory area
and “blit” by hand.

One solution is to create the texture with glTexImage2D as usual, but
supplying NULL for the pixels parameter. Then you can update rectangles of
any size of this texture using glTexSubImage2D.

// MartinOn Wed, 8 Dec 2004, Benjamin Deutsch wrote:

Martin Storsj? wrote:> On Wed, 8 Dec 2004, Benjamin Deutsch wrote:

Until OpenGL 2.0 becomes widespread, any OpenGL texture must have a
height and a width which are a power of 2. But the SDL_Surfaces
created by the TTF_Render functions usually aren’t. So to place the
text in a texture, I’d have to create a new, power-of-2 conforming
SDL_Surface, blit the TTF-created one into it, and free the original.
Or I could create a suitable memory area and “blit” by hand.

One solution is to create the texture with glTexImage2D as usual, but
supplying NULL for the pixels parameter. Then you can update rectangles
of any size of this texture using glTexSubImage2D.

iirc glTexSubImage2D was buggy on some cards/drivers…
is that still true or is it considered safe these days?
because I’d like to use this technique as an optimization myself…

-LIM-

Is it even allowed to pass NULL for the pixel parameter? I’ve had a quick
look at the OpenGL spec, and it only says “pixels points to [image data]”.
Since there is nothing said about NULL pointers, I would assume that a NULL
pointer was invalid.

Feel free to correct me though.

cu,
Nicolai
-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20041208/3083cc0b/attachment.pgpOn Wednesday 08 December 2004 08:25, Martin Storsj? wrote:

One solution is to create the texture with glTexImage2D as usual, but
supplying NULL for the pixels parameter. Then you can update rectangles of
any size of this texture using glTexSubImage2D.

Hello everyone,

I’ve been looking at SDL_ttf, especially with OpenGL in mind, and I’d
like to suggest (and implement) the following extension.

Until OpenGL 2.0 becomes widespread, any OpenGL texture must have a
height and a width which are a power of 2. But the SDL_Surfaces created
by the TTF_Render functions usually aren’t. So to place the text in a
texture, I’d have to create a new, power-of-2 conforming SDL_Surface,
blit the TTF-created one into it, and free the original. Or I could
create a suitable memory area and “blit” by hand.

Looking through the TTF_Render code, I noticed that the returned surface
is created close to the beginning of the function’s body. So it should
be possible to create functions, e.g. TTF_RenderText_Blended_WithSurface
which takes a pre-existing surface and uses it for rendering (or returns
an error if it’s too small). The current TTF_Render functions could then
be wrappers around these new functions, creating and freeing surfaces as
needed.

This could also be useful if one wanted to render a lot of text of
similar size: one could reuse a surface of sufficient size and skip a
lot of memory allocation.

Some questions:

Has this already been tried? Thought of? Discarded?

Would it be worth it, speedwise? Or is text rendering itself far slower
than the additional allocation (twice) and blitting?

Would it make sense to add positional offset parameters to the new
functions? Is this more trouble than it’s worth?

Is there an already existing better solution to the text-to-texture
thing? What do other people do?

I use two different methods depending on the situation. I wave a library
(http://gameprogrammer.com/polyfonts/polyfonts.html) that has a large
number of fonts converted to geometry so I can render them without ever
creating a texture. It’s good for a lot of things, but not all
applications. It include a number of stroke fonts that can be drawn very
quickly with OpenGL, but because of the large number of triangles needed
to represent most outline fonts it can be a bit slow for rendering
antialiased outline fonts.

For outline fonts I usually render each glyph/size/color once when it is
first used by the program and convert it to a texture at that point.
Then I draw text by texture mapping the rectangles for each individual
glyph in a string. Doing that spreads the time cost of rendering strings
out so you don’t have the long pause caused by rendering every glyph in
a font. It also means you only have a texture for each glyph that has
been used. It is surprising how few glyphs are ever used. Then to, it
saves time by never rendering a glyph/size/color more than one.
Typically, if you are rendering a number of strings and you render all
of each string using SDL_ttf you will render the same glyph/size/color
many times. It seems to be a good way to render antialiased text.

If you need 3D text, letters that have been extruded and so on, and are
working in C++, take a look at the FTGL library (google for it). It is a
great tool for rendering TTF fonts using OpenGL. It converts TTF fonts
to geometry and then renders then from that. Lets you do some very nice
text effects.

		Bob PendletonOn Wed, 2004-12-08 at 00:57, Benjamin Deutsch wrote:

Thanks for your time,
Benjamin


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

±-------------------------------------+

Is it even allowed to pass NULL for the pixel parameter? I’ve had a quick
look at the OpenGL spec, and it only says “pixels points to [image data]”.
Since there is nothing said about NULL pointers, I would assume that a NULL
pointer was invalid.

According to the manpages I’m reading, it is allowed:

“In GL version 1.1 or greater, pixels may be a null pointer. In this case
texture memory is allocated to accommodate a texture of width width and
height height. You can then download subtextures to initialize this
texture memory. The image is undefined if the user tries to apply an
uninitialized portion of the texture image to a primitive.”

// MartinOn Wed, 8 Dec 2004, Nicolai Haehnle wrote:

iirc glTexSubImage2D was buggy on some cards/drivers…
is that still true or is it considered safe these days?
because I’d like to use this technique as an optimization myself…

I don’t really know what is common among the driver versions people are
using today. But, I’ve experienced that there are some really awfully
buggy drivers (some ancient Matrox driver, which still is in use at some
computers I happen to use sometimes), with flaws in even the most basic
routines. E.g. glPopMatrix doesn’t restore the matrix at all, in some
cases, glTranslatef doesn’t do anything if you try to translate along the
Y axis only, etc.

The easiest way out is to code according to the specs, and tell the users
to upgrade their drivers if it doesn’t work correctly. In reality, things
are a bit different, of course. But there have to be some limit in how
many driver bugs you try to work around.

I’ve chosen GL 1.1 to be the minimum requirement for some things I code,
and people having drivers with bugs in that functionality really should
upgrade. Except for that Matrox driver, most of the drivers I’ve tried had
no problems when using plain 1.1 functions. (But I don’t think I used
glTexSubImage2D in the programs people tested.)

// MartinOn Wed, 8 Dec 2004, Jonathan Atkins wrote:

For outline fonts I usually render each glyph/size/color once when it is
first used by the program and convert it to a texture at that point.
Then I draw text by texture mapping the rectangles for each individual
glyph in a string.

How do you manage rendering fonts with high sizes and many glyphs? Eg. lately I’ve run into problem that in my card max. texture size is 2048, so anything above it will generate errors (actually it occured with GUI code for edit control, which supports typing very long text in very short field by rendering all string in one texture, then sliding that texture left and using glScissor to show only part of it, but theoretically it could occur in such font pre rendering).

Errr at this point I realized that you don’t render all your glyphs in one big texture but rather in small, single glyph textures. At the link in the end of mail, there’s discussion that similiar approach would fragment your memory, so it would be better to store them in one place and then just create quads and give them appropriate texture coordinates. But there’s that max texture size problem :-/
Generally, wchich one is better to use(considering ease of implementation, speed of rendering, memory usage and maybe other factors)? I’m going to reimplement my font handling manager, so any good answers would help me much (and others too ;-)).

Doing that spreads the time cost of rendering strings
out so you don’t have the long pause caused by rendering every glyph in
a font. It also means you only have a texture for each glyph that has
been used. It is surprising how few glyphs are ever used. Then to, it
saves time by never rendering a glyph/size/color more than one.
Typically, if you are rendering a number of strings and you render all
of each string using SDL_ttf you will render the same glyph/size/color
many times. It seems to be a good way to render antialiased text.

Good idea, I will think about implementing sth similiar.

Benjamin Deutsch: for some more “SDL_TTF & OpenGL fast text rendering” you can take a look here:

Koshmaar

For outline fonts I usually render each glyph/size/color once when it is
first used by the program and convert it to a texture at that point.
Then I draw text by texture mapping the rectangles for each individual
glyph in a string.

How do you manage rendering fonts with high sizes and many glyphs? Eg. lately I’ve run into problem that in my card max. texture size is 2048, so anything above it will generate errors (actually it occured with GUI code for edit control, which supports typing very long text in very short field by rendering all string in one texture, then sliding that texture left and using glScissor to show only part of it, but theoretically it could occur in such font pre rendering).

Errr at this point I realized that you don’t render all your glyphs in one big texture but rather in small, single glyph textures. At the link in the end of mail, there’s discussion that similiar approach would fragment your memory, so it would be better to store them in one place and then just create quads and give them appropriate texture coordinates. But there’s that max texture size problem :-/
Generally, wchich one is better to use(considering ease of implementation, speed of rendering, memory usage and maybe other factors)? I’m going to reimplement my font handling manager, so any good answers would help me much (and others too ;-)).

The answer is “that depends”. The way I describe doesn’t have any
visible effect on runtime performance and only loads glyphs that you
actually use. But, as you point out, it might cause memory fragmentation
problems. I have never seen that problem, and there are several reasons
for that. 1) I always set a video ram budget and stick to it. The budget
is set at a percentage, usually 70% of the size of the memory on the
video cards I’m targeting. 2) Programs follow a fixed pattern in
allocating memory, first allocate all rendering buffers, second allocate
textures and such, then allocate glyphs as they are needed. By
allocating the big stuff first you avoid memory fragmentation. You only
get into problems when you free a bunch of textures and load new ones.
Not usually a problem. 3) I keep a copy of the glyph in ram so I can
free all the texture glyphs and reload them without having to rerender
them.

OTOH, It is not hard to render all of the glyphs of a font into a set
(not one, but several) textures in advance. Just write, or find, a
utility to do it for you. Then keep font data around that has the size,
texture number, and location within a texture for each glyph in the
font. Then you load the textures and use the font. This approach has
very little run time overhead, but it can use a lot of memory for
large fonts (serious problem for CJK fonts) and loads lots of glyphs
that you will never use. But, it might be the best way in memory tight
situations because the memory usage is always 100% predictable in
advance. Which make sticking to a memory budget a lot easier even if it
does use up memory you may never need to use.

You also have to take into account the kind of application you are
writing. If you are writing a typical, you don’t have a lot of text and
don’t use a lot of glyphs. If you are writing a GUI for a word processor
you are going to use a lot of glyphs.

As I said, it depends, use your best judgment based on the application
you are currently building. There is no one answer that is always better
than all the others. And, when using your judgment remember that
tomorrow memory will be cheaper and video cards will be faster.

	Bob PendletonOn Wed, 2004-12-08 at 11:47, Koshmaar wrote:

Doing that spreads the time cost of rendering strings
out so you don’t have the long pause caused by rendering every glyph in
a font. It also means you only have a texture for each glyph that has
been used. It is surprising how few glyphs are ever used. Then to, it
saves time by never rendering a glyph/size/color more than one.
Typically, if you are rendering a number of strings and you render all
of each string using SDL_ttf you will render the same glyph/size/color
many times. It seems to be a good way to render antialiased text.

Good idea, I will think about implementing sth similiar.

Benjamin Deutsch: for some more “SDL_TTF & OpenGL fast text rendering” you can take a look here:

http://www.gamedev.net/community/forums/topic.asp?topic_id=286310&whichpage=1

Koshmaar


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

±-------------------------------------+

Hello again,

thanks everyone for all the replies so far!

For outline fonts I usually render each glyph/size/color once when it is
first used by the program and convert it to a texture at that point.
Then I draw text by texture mapping the rectangles for each individual
glyph in a string.
[…]

I had thought of this as well, but it seemed to be quite a bit of work
to set up such a system. Since my strings don’t change that much, and
SDL_ttf seems to cache already rendered glyphs (at least some of them?),
I was mainly concerned about the “unnecessary” overhead of surface
creation and extra blitting.

I might still try Martin’s suggestion with glTexSubImage2D, but
rendering the glyphs to GL textures is probably the way to go; if not
now, then in my next project(s). So there goes my current itch with
SDL_ttf…

One thing though: do/can you handle kerning with this method? SDL_ttf
seems to use kerning when rendering strings (and depending on the font,
this can be very useful), but does not make this information available
externally. Should I rather use freetype directly?

(As to “one texture per color”: You do know you can render all glyphs
white, and then use glColor before rendering, right? Or am I missing
something ?-)

If you need 3D text, letters that have been extruded and so on, and are
working in C++, take a look at the FTGL library (google for it). It is a
great tool for rendering TTF fonts using OpenGL. It converts TTF fonts
to geometry and then renders then from that. Lets you do some very nice
text effects.

It does look great, but my current project is in straight C (though more
for “lets see how this works/feels” than any real preference). The next
will be in python…

Thanke again,
Benjamin

OTOH, It is not hard to render all of the glyphs of a font into a set
(not one, but several) textures in advance. Just write, or find, a
utility to do it for you.

Well, I wanted to make my FontMgr do this internally at startup - I say “load font xxx” and it will do all the dirty job of loading font, texture creation, merging, error handling etc. But it would be very hard to write generalized function that would cope with any set of font attributes and flexibility in my situation is needed (game I’m writing will be totally expendable and open source so user could use any font with any settings; and yes, I take into account that fonts with size ie. 2500 just can’t be managed in any reasonable way but that’s not the point). Also, I want to use .ttf files rather then external images as it’s counter intiutive for me.

You also have to take into account the kind of application you are
writing. If you are writing a typical, you don’t have a lot of text and
don’t use a lot of glyphs. If you are writing a GUI for a word processor
you are going to use a lot of glyphs.

Actually I’m writing game engine with support for GUIs, so there won’t be so much text like in word processor, but (theoretically) engine should be so flexible to behave well in every possible situation.

As I said, it depends, use your best judgment based on the application
you are currently building. There is no one answer that is always better
than all the others. And, when using your judgment remember that
tomorrow memory will be cheaper and video cards will be faster.

Ok, (once again) you’ve persuaded me to go your way, thanks :wink: Load ttf font, if text needs to be rendered then parse all glyphs and create individual textures for them, then glue them and render on screen. Also there will be additional function to render passed string on one texture, so rendering totally static texts will be very fast.

Koshmaar

One thing though: do/can you handle kerning with this method? SDL_ttf seems
to use kerning when rendering strings (and depending on the font, this can be
very useful), but does not make this information available externally. Should
I rather use freetype directly?

Using TTF_GlyphMetrics, you can retrieve some kind of information which
can be used for kerning.

You could of course store all the retrieved information about all the
glyphs, but I used another approach.

My implementation, (which is heavily based on the tutorial at
http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=43), creates one
display list for every character, which draws that glyph and translates
the correct distance. That makes drawing text as simple as a call to
glListBase and glCallLists.

But, when I think about it now, I suspect that this isn’t really
necessary, and is only a waste of vram.

// MartinOn Wed, 8 Dec 2004, Benjamin Deutsch wrote:

Hi there,

Well, I wanted to make my FontMgr do this internally at startup - I
say “load font xxx” and it will do all the dirty job of loading font,
texture creation, merging, error handling etc. But it would be very
hard to write generalized function that would cope with any set of
font attributes and flexibility in my situation is needed (game I’m
writing will be totally expendable and open source so user could use
any font with any settings; and yes, I take into account that fonts
with size ie. 2500 just can’t be managed in any reasonable way but
that’s not the point). Also, I want to use .ttf files rather then
external images as it’s counter intiutive for me.

If you manage to manage to get this written, would you mind sharing your
code ?-)

Bye,
Benjamin

If you manage to manage to get this written, would you mind sharing your
code ?-)

Well, you know, my engine is open source… you know the answer :wink: Though I will start doing it after 2 weeks or so, in this case maybe Bob Pendleton could share his version (and I would be interested in it too).

Koshmaar

Hello again,

thanks everyone for all the replies so far!

For outline fonts I usually render each glyph/size/color once when it is
first used by the program and convert it to a texture at that point.
Then I draw text by texture mapping the rectangles for each individual
glyph in a string.
[…]

I had thought of this as well, but it seemed to be quite a bit of work
to set up such a system. Since my strings don’t change that much, and
SDL_ttf seems to cache already rendered glyphs (at least some of them?),
I was mainly concerned about the “unnecessary” overhead of surface
creation and extra blitting.

I might still try Martin’s suggestion with glTexSubImage2D, but
rendering the glyphs to GL textures is probably the way to go; if not
now, then in my next project(s). So there goes my current itch with
SDL_ttf…

One thing though: do/can you handle kerning with this method? SDL_ttf
seems to use kerning when rendering strings (and depending on the font,
this can be very useful), but does not make this information available
externally. Should I rather use freetype directly?

SDL_ttf gives you all the info you need.

(As to “one texture per color”: You do know you can render all glyphs
white, and then use glColor before rendering, right? Or am I missing
something ?-)

No, I am. I originally wrote the code for use with the 2D SDL and
converted it without really thinking about the abilities of OpenGL.
Thank you very much for pointing this out.On Wed, 2004-12-08 at 14:36, Benjamin Deutsch wrote:

If you need 3D text, letters that have been extruded and so on, and are
working in C++, take a look at the FTGL library (google for it). It is a
great tool for rendering TTF fonts using OpenGL. It converts TTF fonts
to geometry and then renders then from that. Lets you do some very nice
text effects.

It does look great, but my current project is in straight C (though more
for “lets see how this works/feels” than any real preference). The next
will be in python…

Thanke again,
Benjamin


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

±-------------------------------------+

I’ve posted it before, but here it is again:On Wed, 2004-12-08 at 15:34, Koshmaar wrote:

If you manage to manage to get this written, would you mind sharing your
code ?-)

Well, you know, my engine is open source… you know the answer :wink: Though I will start doing it after 2 weeks or so, in this case maybe Bob Pendleton could share his version (and I would be interested in it too).

Koshmaar


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[((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_Shaded(ttfFont, 
                             letter, 
                             foreground, 
                             background);

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

  if (NULL != g1)
  {
    glyphs[((int)c)].pic = g1;
    glyphs[((int)c)].tex = loadTextureColorKey(g1, texcoord, 0, 0,

0);
glyphs[((int)c)].texMinX = texcoord[0];
glyphs[((int)c)].texMinY = texcoord[1];
glyphs[((int)c)].texMaxX = texcoord[2];
glyphs[((int)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[((int)*text)].maxx;
    advance = glyphs[((int)*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[((int)*text)].texMinX;
    texMinY = glyphs[((int)*text)].texMinY;
    texMaxX = glyphs[((int)*text)].texMaxX;
    texMaxY = glyphs[((int)*text)].texMaxY;

    left   = x;
    right  = x + glyphs[((int)*text)].pic->w;
    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;

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


The code is designed so you can just drop it into an existing C++
program. If you are picky about .h and .cpp division you’ll need to
figure that out for your self. And, if you are working in C then, well
you’ll have to convert it.

BTW, it is covered by the LGPL

	Bob Pendleton

SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

±-------------------------------------+

Hello,

Bob Pendleton was kind enough to share some code:

I’ve posted it before, but here it is again:


class Font
{
[ Code snipped ]

The code is designed so you can just drop it into an existing C++
program. If you are picky about .h and .cpp division you’ll need to
figure that out for your self. And, if you are working in C then, well
you’ll have to convert it.

Thanks alot! Conversion should be straightforward enough. As discussed
before, you may want to switch to TTF_RenderText_Blended and use the
nice alpha channel and tinting abilities of OpenGL (as well as avoid
some format conversions).

As to kerning: what I’m referring to is a font’s ability to place "AV"
closer together than “VV”. In freetype: FT_Get_Kerning. It’s not that
critical, but depending on the font, it may look nicer (ligatures, too,
but even freetype doesn’t handle this !-)

Thanks again to all who contributed!

Benjamin

I have never been able to make TTF_RenderText_Blended work for me. And,
yes, I am using the latest SDL_ttf from cvs. Don’t know what the problem
is, I just can’t make it work. Could you post code that uses it and
makes it work?

BTW, here is a helper function that is required to make my font class
work. I forgot to post it with the original code:On Thu, 2004-12-09 at 00:31, Benjamin Deutsch wrote:

Hello,

Bob Pendleton was kind enough to share some code:

I’ve posted it before, but here it is again:


class Font
{
[ Code snipped ]

The code is designed so you can just drop it into an existing C++
program. If you are picky about .h and .cpp division you’ll need to
figure that out for your self. And, if you are working in C then, well
you’ll have to convert it.

Thanks alot! Conversion should be straightforward enough. As discussed
before, you may want to switch to TTF_RenderText_Blended and use the
nice alpha channel and tinting abilities of OpenGL (as well as avoid
some format conversions).


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

// Create a texture from a surface. Set the alpha according
// to the color key. Pixels that match the color key get an
// alpha of zero while all other pixels get an alpha of
// one.

GLuint loadTextureColorKey(SDL_Surface *surface,
GLfloat *texcoord,
int ckr,
int ckg,
int ckb)
{
GLuint texture;
int w, h;
SDL_Surface *image;
SDL_Rect area;
Uint32 colorkey;

// Use the surface width and height expanded to powers of 2

w = powerOfTwo(surface->w);
h = powerOfTwo(surface->h);
texcoord[0] = 0.0f; // Min X
texcoord[1] = 0.0f; // Min Y
texcoord[2] = (GLfloat)surface->w / w; // Max X
texcoord[3] = (GLfloat)surface->h / h; // Max Y

image = SDL_CreateRGBSurface(
SDL_SWSURFACE,
w, h,
32,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN // OpenGL RGBA masks
0x000000FF,
0x0000FF00,
0x00FF0000,
0xFF000000
#else
0xFF000000,
0x00FF0000,
0x0000FF00,
0x000000FF
#endif
);
if (image == NULL)
{
return 0;
}

// Set up so that colorkey pixels become transparent

colorkey = SDL_MapRGBA(image->format, ckr, ckg, ckb, 0);
SDL_FillRect(image, NULL, colorkey);

colorkey = SDL_MapRGBA(surface->format, ckr, ckg, ckb, 0);
SDL_SetColorKey(surface, SDL_SRCCOLORKEY, colorkey);

// Copy the surface into the GL texture image
area.x = 0;
area.y = 0;
area.w = surface->w;
area.h = surface->h;
SDL_BlitSurface(surface, &area, image, &area);

// Create an OpenGL texture for the image

glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
w, h,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
image->pixels);

SDL_FreeSurface(image); // No longer needed

return texture;
}

	Bob Pendleton

As to kerning: what I’m referring to is a font’s ability to place "AV"
closer together than “VV”. In freetype: FT_Get_Kerning. It’s not that
critical, but depending on the font, it may look nicer (ligatures, too,
but even freetype doesn’t handle this !-)

Thanks again to all who contributed!

Benjamin


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

±-------------------------------------+

I’ve posted it before, but here it is again:

Thanks for the code!

I have never been able to make TTF_RenderText_Blended work for me. And,
yes, I am using the latest SDL_ttf from cvs. Don’t know what the problem
is, I just can’t make it work. Could you post code that uses it and
makes it work?

??? I’m not using latest SDL nor SDL_TTF and never had any problems with blended, solid or shaded mode.

Here’s little, plain, nasty and stupid ttf test code I’ve found on my hard drive, it’s actually working for me.

#include <stdio.h>
#include <stdlib.h>
#include
#include
#include <time.h>

#include <SDL.h> // All SDL App’s need this

#include <SDL_TTF.h> // It’s our new buddy!!

int main( int argc, char* argv[] ) {

if( SDL_Init(SDL_INIT_VIDEO)==(-1) ) {

printf(“Could not initialize SDL: %s.\n”, SDL_GetError());

exit(-1);

}

SDL_Surface *screen;

int WINWIDTH = 800, WINHEIGHT = 600, BPP = 32;

screen = SDL_SetVideoMode( WINWIDTH,WINHEIGHT, BPP, SDL_SWSURFACE | SDL_FULLSCREEN );

if( screen == NULL ) {

fprintf(stderr, “Couldn’t set %ix%ix%i video mode: %s\n”, WINWIDTH,WINHEIGHT,BPP, SDL_GetError());

exit(1);

}

//SDL_ShowCursor( SDL_DISABLE );

TTF_Init();

TTF_Font *fntCourier = TTF_OpenFont( “cour.ttf”, 25 );

SDL_Color clrFg = {220,50,50,0}; // Blue (“Fg” is foreground)

SDL_Color clrBg = {0,0,0,0};

SDL_Rect rcDest = {20,20,0,0};

SDL_Surface * sText = TTF_RenderText_Solid( fntCourier, “Courier 12”, clrFg);

SDL_BlitSurface( sText,NULL, screen,&rcDest );

rcDest.y = 60;

sText = TTF_RenderText_Shaded( fntCourier, “Courier 12!@#$%^&*()_+[]”, clrFg, clrBg );

SDL_BlitSurface( sText,NULL, screen,&rcDest );

rcDest.y = 100;

sText = TTF_RenderText_Blended( fntCourier, “So we met there, and started to bangle \n each other and drink green tea (YEEEAH!).”, clrFg);

SDL_BlitSurface( sText,NULL, screen,&rcDest );

fprintf(stderr, " Width: %i Height: %i", sText->w, sText->h);

SDL_Flip(screen);

SDL_Event event ;

for ( ; ; )

{

if ( SDL_PollEvent ( &event ) )
{
if ( event.type == SDL_KEYDOWN ) break ;
}

}

SDL_FreeSurface( sText );

TTF_CloseFont( fntCourier );

TTF_Quit();

SDL_Quit();
return 0;

}

HTH

Koshmaar

I’ve posted it before, but here it is again:

Thanks for the code!

I have never been able to make TTF_RenderText_Blended work for me. And,
yes, I am using the latest SDL_ttf from cvs. Don’t know what the problem
is, I just can’t make it work. Could you post code that uses it and
makes it work?

I should have been more clear, makes it work with OpenGL.

	Bob PendletonOn Thu, 2004-12-09 at 10:44, Koshmaar wrote:

??? I’m not using latest SDL nor SDL_TTF and never had any problems with blended, solid or shaded mode.

Here’s little, plain, nasty and stupid ttf test code I’ve found on my hard drive, it’s actually working for me.

#include <stdio.h>
#include <stdlib.h>
#include
#include
#include <time.h>

#include <SDL.h> // All SDL App’s need this

#include <SDL_TTF.h> // It’s our new buddy!!

int main( int argc, char* argv[] ) {

if( SDL_Init(SDL_INIT_VIDEO)==(-1) ) {

printf(“Could not initialize SDL: %s.\n”, SDL_GetError());

exit(-1);

}

SDL_Surface *screen;

int WINWIDTH = 800, WINHEIGHT = 600, BPP = 32;

screen = SDL_SetVideoMode( WINWIDTH,WINHEIGHT, BPP, SDL_SWSURFACE | SDL_FULLSCREEN );

if( screen == NULL ) {

fprintf(stderr, “Couldn’t set %ix%ix%i video mode: %s\n”, WINWIDTH,WINHEIGHT,BPP, SDL_GetError());

exit(1);

}

//SDL_ShowCursor( SDL_DISABLE );

TTF_Init();

TTF_Font *fntCourier = TTF_OpenFont( “cour.ttf”, 25 );

SDL_Color clrFg = {220,50,50,0}; // Blue (“Fg” is foreground)

SDL_Color clrBg = {0,0,0,0};

SDL_Rect rcDest = {20,20,0,0};

SDL_Surface * sText = TTF_RenderText_Solid( fntCourier, “Courier 12”, clrFg);

SDL_BlitSurface( sText,NULL, screen,&rcDest );

rcDest.y = 60;

sText = TTF_RenderText_Shaded( fntCourier, “Courier 12!@#$%^&*()_+[]”, clrFg, clrBg );

SDL_BlitSurface( sText,NULL, screen,&rcDest );

rcDest.y = 100;

sText = TTF_RenderText_Blended( fntCourier, “So we met there, and started to bangle \n each other and drink green tea (YEEEAH!).”, clrFg);

SDL_BlitSurface( sText,NULL, screen,&rcDest );

fprintf(stderr, " Width: %i Height: %i", sText->w, sText->h);

SDL_Flip(screen);

SDL_Event event ;

for ( ; ; )

{

if ( SDL_PollEvent ( &event ) )
{
if ( event.type == SDL_KEYDOWN ) break ;
}

}

SDL_FreeSurface( sText );

TTF_CloseFont( fntCourier );

TTF_Quit();

SDL_Quit();
return 0;

}

HTH

Koshmaar


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

±-------------------------------------+