Trouble (I think) with alpha channel using SDL_ttf

Hi,

I’ve taken over a project that has a function (see below) that is supposed to
return a SDL_Surface* containing text with a black outline. The surface
surrounding the text is supposed to be transparent. However, the entire
SDL_Surface comes out transparent. I have tested having the function return
some of the intermediate surfaces, and everything other than the "tmp"
surfaces immediately returned by TTF_RenderUTF8_Blended() comes out
transparent. Do I need to do something with SDL_SetAlpha() on the "tmp"
surfaces before I blit them to the “out” surface?

#if SDL_BYTEORDER == SDL_BIG_ENDIAN
#define rmask 0xff000000
#define gmask 0x00ff0000
#define bmask 0x0000ff00
#define amask 0x000000ff
#else
#define rmask 0x000000ff
#define gmask 0x0000ff00
#define bmask 0x00ff0000
#define amask 0xff000000
#endif

SDL_Surface* black_outline(unsigned char *t, TTF_Font *font, SDL_Color *c) {
SDL_Surface *out, *tmp, *tmp2;
SDL_Rect dstrect;

tmp = font, t, black);

tmp2 = SDL_CreateRGBSurface(SDL_SWSURFACE,
                                                 (tmp->w)+5,
                                                 (tmp->h)+5,
                                                  32, 
                                                  rmask, gmask,
                                                  bmask, amask);

out = SDL_DisplayFormatAlpha(tmp2);
SDL_FreeSurface(tmp2);

dstrect.w = tmp->w;
dstrect.h = tmp->h;

    for (dstrect.x = 1; dstrect.x < 4; dstrect.x++)
      for (dstrect.y = 1; dstrect.y < 4; dstrect.y++)
        SDL_BlitSurface( tmp, NULL, out, &dstrect );

    /* NOTE: if I return "out" at this point it is transparent */

SDL_FreeSurface(tmp);

/* --- Put the color version of the text on top! --- */
tmp = TTF_RenderUTF8_Blended(font, t, *c);
dstrect.x = dstrect.y = 2;
SDL_BlitSurface(tmp, NULL, out, &dstrect);

SDL_FreeSurface(tmp);

/* --- Convert to the screen format for quicker blits --- */

tmp = SDL_DisplayFormatAlpha(out);
SDL_FreeSurface(out);

return tmp;

}

Thanks for any help, and sorry if this is a naive/newbie question.–
David Bruce

Here is what I use to create outline text. Hope it helps.

typedef unsigned char * byte;
SDL_Surface *Text::render() {
SDL_Color c;
c.r = c.g = c.b = 255;
SDL_Surface *tmp = TTF_RenderUTF8_Blended( fonts[size], text.c_str(), c );
if ( !tmp ) {
fprintf( stderr, “TTF: %s.\n”, TTF_GetError() );
SDL_Quit();
exit( 1 );
}

SDL_Surface *surf = SDL_CreateRGBSurface( SDL_SWSURFACE, tmp->w+2, tmp->h+2, 32, 0xff, 0xff00, 0xff0000, 0xff000000 );
for ( int x = 0; x < surf->w; x++ ) {
	for ( int y = 0; y < surf->h; y++ ) {
		byte *dr = (byte*)surf->pixels + surf->pitch * y + x * 4 + 0;
		byte *dg = (byte*)surf->pixels + surf->pitch * y + x * 4 + 1;
		byte *db = (byte*)surf->pixels + surf->pitch * y + x * 4 + 2;
		byte *da = (byte*)surf->pixels + surf->pitch * y + x * 4 + 3;

		if ( x > 0 && x < surf->w - 1 && y > 0 && y < surf->h - 1 ) {
			byte sa = *((byte*)tmp->pixels + tmp->pitch * (y-1) + (x-1) * 4 + 3);
			*dr = *dg = *db = sa;
		} else {
			*dr = *dg = *db = 0;
		}
		*da = 0;

		int r = 1;
		int fromx = x-r;
		if ( fromx < 0 ) fromx = 0;
		int tox = x+r+1;
		if ( tox > surf->w ) tox = surf->w;
		int fromy = y-r;
		if ( fromy < 0 ) fromy = 0;
		int toy = y+r+1;
		if ( toy > surf->h ) toy = surf->h;

		byte ma = 0;
		for ( int tx = fromx; tx < tox; tx++ ) {
			if ( tx > 0 && tx < surf->w - 1 ) {
				for ( int ty = fromy; ty < toy; ty++ ) {
					if ( ty > 0 && ty < surf->h - 1 ) {
						byte sa = *((byte*)tmp->pixels + tmp->pitch * (ty-1) + (tx-1) * 4 + 3);
						if ( sa > ma ) ma = sa;
					}
				}
			}
		}
		*da = ma;
	}
}

SDL_FreeSurface( tmp );

return surf;

}On Tue, Apr 03, 2007 at 12:35:34PM -0400, David Bruce wrote:

Hi,

I’ve taken over a project that has a function (see below) that is supposed to
return a SDL_Surface* containing text with a black outline.