Pre-blitting in multiline text

Hello,

I’m working with SDL 1.2 in a multiline textfield class using SDL_ttf library. I’m using a vector to store each line of the textfield but the problem comes when I try to render them into the surface.
My idea is to render each one into one surface first and then blit that surface with the screen surface.
I think my error is due my poor knowledge or bad understanding about the surface blitting.

I?ve tried rendering the first line with TTF_RenderText_Solid getting a surface SRF1. The next line with the same ttf function getting a SRF2. Then I tried to blit SRF2 into SRF1 and modifying the Y value of the Rect (to put the second line below the first one). The result in the screen is only the first line is displayed. (I guess is because the width and higth of the SRF1).

Also I’ve tried to create a new surface with SDL_CreateRGBSurface (with precise dimensions for the all lines can fit) and then blit every line into that surface, and then blit it with the screen surface.
The result is the all lines are displayed but with a black background covering that part of the screen.

So how I can make this pre-blitting into a surface and then blit that surface into the screen one? The direct blitting of every line into screen surface doesn’t work for me (for my program logic).

Thanks in advance for any help you can give me.

Nicolas.

Hey,

What does your call to SDL_CreateRGBSurface() look like? You either want
to enable alpha blending and make the background transparent or disable
alpha blending and set a colorkey value (probably black from your
description).

Another option is NFont. The development version has some textbox methods.

Jonny DOn Sun, Feb 5, 2012 at 10:33 PM, psychoalienx wrote:

**
Hello,

I’m working with SDL 1.2 in a multiline textfield class using SDL_ttf
library. I’m using a vector to store each line of the textfield but the
problem comes when I try to render them into the surface.
My idea is to render each one into one surface first and then blit that
surface with the screen surface.
I think my error is due my poor knowledge or bad understanding about the
surface blitting.

I?ve tried rendering the first line with TTF_RenderText_Solid getting a
surface SRF1. The next line with the same ttf function getting a SRF2. Then
I tried to blit SRF2 into SRF1 and modifying the Y value of the Rect (to
put the second line below the first one). The result in the screen is only
the first line is displayed. (I guess is because the width and higth of the
SRF1).

Also I’ve tried to create a new surface with SDL_CreateRGBSurface (with
precise dimensions for the all lines can fit) and then blit every line into
that surface, and then blit it with the screen surface.
The result is the all lines are displayed but with a black background
covering that part of the screen.

So how I can make this pre-blitting into a surface and then blit that
surface into the screen one? The direct blitting of every line into screen
surface doesn’t work for me (for my program logic).

Thanks in advance for any help you can give me.

Nicolas.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

SDL_gfx provide the function SDL_gfxBlitRGBA (a custom blitter) that can
be used to “compose” RGBA surfaces while maintaining alpha. I’ve used it
in the past to create “textbox” implementations based on SDL_ttf that
maintain full font antialiasing.

See
http://www.ferzkopp.net/Software/SDL_gfx-2.0/Docs/html/_s_d_l__gfx_blit_func_8c.html
for API info.

Hope that helps,
–AndreasOn 2/5/12 7:33 PM, psychoalienx wrote:

Hello,

I’m working with SDL 1.2 in a multiline textfield class using SDL_ttf
library. I’m using a vector to store each line of the textfield but
the problem comes when I try to render them into the surface.
My idea is to render each one into one surface first and then blit
that surface with the screen surface.
I think my error is due my poor knowledge or bad understanding about
the surface blitting.

I?ve tried rendering the first line with TTF_RenderText_Solid getting
a surface SRF1. The next line with the same ttf function getting a
SRF2. Then I tried to blit SRF2 into SRF1 and modifying the Y value of
the Rect (to put the second line below the first one). The result in
the screen is only the first line is displayed. (I guess is because
the width and higth of the SRF1).

Also I’ve tried to create a new surface with SDL_CreateRGBSurface
(with precise dimensions for the all lines can fit) and then blit
every line into that surface, and then blit it with the screen surface.
The result is the all lines are displayed but with a black background
covering that part of the screen.

So how I can make this pre-blitting into a surface and then blit that
surface into the screen one? The direct blitting of every line into
screen surface doesn’t work for me (for my program logic).

Thanks in advance for any help you can give me.

Nicolas.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

First thanks for your answers,

Jonny,

My code looks like this

Code:

_srf=SDL_CreateRGBSurface(SDL_HWSURFACE | SDL_SRCALPHA ,w,(numLines*(_format->leading + _format->size)),24,0,0,0,0);
SDL_SetAlpha(_srf,SDL_SRCALPHA | SDL_RLEACCEL,0);
do{
_auxSrf=TTF_RenderText_Solid(_format->_font, textLines[i].c_str(), _format->textColor);
SDL_Rect rect;
rect.x=getX();
rect.y=getY()+(i*(_format->leading + _format->size));
if(SDL_BlitSurface(_auxSrf,NULL,_srf,&rect)) printf(“No se pudo copiar en Screen %s”,SDL_GetError());
i++;
}while(i < textLines.size());

When I set the alpha parameter in SDL_SetAlpha function to 255, the whole surface disappear including the text. That makes transparent the entire surface, not just the background. I had also tried with SDL_SetColorKey (black) and disabled the alpha blending: SDL_SetAlpha(_srf,SDL_RLEACCEL,0);

Now, I will try with the SDL_gfx that Andreas suggests, unless you can see what I am doing wrong.

Thanks again.

Well, there is a lot going on here. It should work fine without using an
alpha channel. Don’t use any SDL_SetAlpha() calls, don’t use SDL_SRCALPHA,
and set the color key of _srf to black.

I think the main problem with your alpha-blending approach is that you pass
0 as the Amask argument to SDL_CreateRGBSurface(). I recommend using a
32-bit surface and passing explicit mask arguments (from the old docs):
SDL_Surface *surface;
Uint32 rmask, gmask, bmask, amask;

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

surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32,
                               rmask, gmask, bmask, amask);

You should also stick to software surfaces. SDL 1.2 does not do much in
the way of hardware acceleration and if you’re doing alpha blending, you
might just be making it slower by using HW surfaces.

If you have a blank RGBA surface, blitting to it will not change the alpha
values, so you’ll see nothing at first. Use SDL_SetAlpha(surface, 0,
surface->format->alpha) to disable alpha-blending, then do your blitting
onto the new surface. TTF_RenderText_Solid() should have set the color key
for you. Use SDL_SetAlpha(surface, SDL_SRCALPHA, surface->format->alpha)
to enable alpha-blending again when you’re done. The ‘alpha’ argument
won’t actually make any difference if you’re using alpha-blending. This
should work with TTF_RenderText_Blended() too, so you can get even
nicer-looking text.

Last thing. In your loop there, you need SDL_FreeSurface(_auxSrf) after
the blit to free the surface that SDL_ttf allocated. You will probably
need to find a good place to free _srf too, but after you’re done using it.

Jonny DOn Mon, Feb 6, 2012 at 7:15 PM, psychoalienx wrote:

**
First thanks for your answers,

Jonny,

My code looks like this

Code:

_srf=SDL_CreateRGBSurface(SDL_HWSURFACE | SDL_SRCALPHA
,w,(numLines*(_format->leading + _format->size)),24,0,0,0,0);
SDL_SetAlpha(_srf,SDL_SRCALPHA | SDL_RLEACCEL,0);
do{
_auxSrf=TTF_RenderText_Solid(_format->_font, textLines[i].c_str(),
_format->textColor);
SDL_Rect rect;
rect.x=getX();
rect.y=getY()+(i*(_format->leading + _format->size));
if(SDL_BlitSurface(_auxSrf,NULL,_srf,&rect)) printf(“No se pudo copiar
en Screen %s”,SDL_GetError());
i++;
}while(i < textLines.size());

When I set the alpha parameter in SDL_SetAlpha function to 255, the whole
surface disappear including the text. That makes transparent the entire
surface, not just the background. I had also tried with SDL_SetColorKey
(black) and disabled the alpha blending: SDL_SetAlpha(_srf,SDL_RLEACCEL,0);

Now, I will try with the SDL_gfx that Andreas suggests, unless you can see
what I am doing wrong.

Thanks again.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Jonny,
You were right. The masks were the problem. I didn’t even need to use either SDL_SetAlpha or SDL_SetColorKey functions.
That made clear for me the Surface and Blitting functions behavior.

Thank you so much.

Jonny D wrote:> Well, there is a lot going on here. ?It should work fine without using an alpha channel. ?Don’t use any SDL_SetAlpha() calls, don’t use SDL_SRCALPHA, and set the color key of _srf to black.

I think the main problem with your alpha-blending approach is that you pass 0 as the Amask argument to SDL_CreateRGBSurface(). ?I recommend using a 32-bit surface and passing explicit mask arguments (from the old docs):
? ? SDL_Surface *surface;
? ? Uint32 rmask, gmask, bmask, amask;

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

? ? surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?rmask, gmask, bmask, amask);

You should also stick to software surfaces. ?SDL 1.2 does not do much in the way of hardware acceleration and if you’re doing alpha blending, you might just be making it slower by using HW surfaces.

If you have a blank RGBA surface, blitting to it will not change the alpha values, so you’ll see nothing at first. ?Use SDL_SetAlpha(surface, 0, surface->format->alpha) to disable alpha-blending, then do your blitting onto the new surface. ?TTF_RenderText_Solid() should have set the color key for you. ?Use SDL_SetAlpha(surface, SDL_SRCALPHA, surface->format->alpha) to enable alpha-blending again when you’re done. ?The ‘alpha’ argument won’t actually make any difference if you’re using alpha-blending. ?This should work with TTF_RenderText_Blended() too, so you can get even nicer-looking text.

Last thing. ?In your loop there, you need SDL_FreeSurface(_auxSrf) after the blit to free the surface that SDL_ttf allocated. ?You will probably need to find a good place to free _srf too, but after you’re done using it.

Jonny D

On Mon, Feb 6, 2012 at 7:15 PM, psychoalienx <@psychoalienx (@psychoalienx)> wrote:

  First thanks for your answers,

Jonny,

My code looks like this

Code:

_srf=SDL_CreateRGBSurface(SDL_HWSURFACE | SDL_SRCALPHA ,w,(numLines*(_format->leading + _format->size)),24,0,0,0,0);
SDL_SetAlpha(_srf,SDL_SRCALPHA | SDL_RLEACCEL,0);
do{
? ?_auxSrf=TTF_RenderText_Solid(_format->_font, textLines[i].c_str(), _format->textColor);
? ?SDL_Rect rect;
? ?rect.x=getX();
? ?rect.y=getY()+(i*(_format->leading + _format->size));
? ?if(SDL_BlitSurface(_auxSrf,NULL,_srf,&rect)) printf(“No se pudo copiar en Screen %s”,SDL_GetError());
? ?i++;
}while(i < textLines.size());

When I set the alpha parameter in SDL_SetAlpha function to 255, the whole surface disappear including the text. That makes transparent the entire surface, not just the background. I had also tried with SDL_SetColorKey (black) and disabled the alpha blending: SDL_SetAlpha(_srf,SDL_RLEACCEL,0);

Now, I will try with the SDL_gfx that Andreas suggests, unless you can see what I am doing wrong.

Thanks again.


SDL mailing list
SDL at lists.libsdl.org (SDL at lists.libsdl.org)
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org (http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org)