[SDL] drawing a rectangle in a surface

Started by
8 comments, last by vanzukeus 14 years, 1 month ago
Hi all, I'm using SDL and SDL_gfx for primitives like fillRectangle etc. I have a problem, I want to draw a rectangle in a SDL_surface and after display the content of this surface in the screen (the main SDL_surface). I'm doing this:

SDL_Surface* test;
test = new SDL_Surface();
//test->h=300;
//test->w=300;
boxRGBA(test,22,33,44,100,144,2,3,122);
CSurface::OnDraw(Surf_Display,test,1,1);

with:
 
bool CSurface::OnDraw(SDL_Surface* Surf_Dest, SDL_Surface* Surf_Src, int X, int Y) {
	if(Surf_Dest == NULL || Surf_Src == NULL) {
		return false;
	}

	SDL_Rect DestR;

	DestR.x = X;
	DestR.y = Y;

	SDL_BlitSurface(Surf_Src, NULL, Surf_Dest, &DestR);

	return true;
}
I get that test has all the fields undefined and I have not got it why.. Thanks in advance!
Advertisement
First you should create a surface with SDL_CreateRGBSurface() instead of new SDL_Surface(). Then, if you set a DestR rect, be sure to at least put a size (.w and .h) or else it will be 0 and won't do anything. Finally, for a simple rectangle you don't have to usr SDL_gfx, you can simply use SDL_FillRect().
You've allocated memory for an SDL_Surface struct, that's all. None of that data is filled in. You want SDL to create a new surface that you can use, then draw your rect on that and finally blit that surface onto the screen:
test = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, primary->format->BitsPerPixel, 			primary->format->Rmask, primary->format->Gmask, primary->format->Bmask, primary->format->Amask);// check for successif (!test)    throw std::exception(); // failed to create surface!

Remember to use SDL_FreeSurface() to free surfaces, don't delete them.
If I put my 2 cents in and get a penny for my thoughts, where does my other penny go?
thanks :)
Now I'm going to try it. Anyway, I need a filled rectangle. SDL_gfx provides circle and other stuff also and it is portable in almost all the OS that support SDL if I rimember well. What do you think about this library?
I found the signature of that method:
SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);

but.. if I want to use SDL_gfx methods this SDL_CreateRGBSurface seems useless
The call to SDL_CreateRGBSurface is useless in this case.
What you should use, as Dunge has already mentioned, is SDL_FillRect.
What? If you're using an appropriate video format, just enable alpha blending

// SRCALPHA = enable alpha blending on this surface//	*note that this is a 32bit surface, so if your primary surface isn't also 32 bits//	 then your frame rate will suffertest = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, w, h, 32, 	primary->format->Rmask, primary->format->Gmask, primary->format->Bmask, 0);if (!test)	throw std::exception(); // error creating surface// apparently strangeness can occur when Amask != 0 while setting alpha channel, so// this is SDL's workaround//		set this surface's alpha value to 255 (fully opaque).  per-pixel alpha values//		take precedence over per-surface alpha if (SDL_SetAlpha(test, SDL_SRCALPHA, SDL_ALPHA_OPAQUE) == -1)	throw std::exception(); // error setting surface alpha value

I'll also point out that you don't need alpha channels for boxRGBA, it programmatically alphablends with the destination and doesn't use an alpha channel.
If I put my 2 cents in and get a penny for my thoughts, where does my other penny go?
Guys thanks for the infos,

I tried both of your advices:

int w=50;	int h=50;	test = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, w, h, 32,155,55,55, 55);	if (!test)		throw std::exception(); // error creating surface	// apparently strangeness can occur when Amask != 0 while setting alpha channel, so	// this is SDL's workaround	//		set this surface's alpha value to 255 (fully opaque).  per-pixel alpha values	//		take precedence over per-surface alpha 	if (SDL_SetAlpha(test, SDL_SRCALPHA, SDL_ALPHA_OPAQUE) == -1)		throw std::exception(); // error setting surface alpha value		CSurface::OnDraw(Surf_Display,test,22,22);


and
SDL_Surface* test;SDL_Rect *rect = new SDL_Rect();rect->x=100;rect->y=100;rect->w=100;rect->h=100;test = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, 200, 200, 32,155,55,55, 55);Uint32 rectcolor = SDL_MapRGB( test->format, 33, 144, 55 );//boxRGBA(test,22,33,44,100,144,2,3,122);SDL_FillRect( test, rect, rectcolor );CSurface::OnDraw(Surf_Display,test,1,1);


Both don't work :(
they compile, no error at run-time but no visible rectangle in the screen too :D

Quote:Original post by vanzukeus
test = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, 200, 200, 32,155,55,55, 55);


The last 4 parameters to SDL_CreateRGBSurface are not colour values. They are there to tell the surface how to pack the colour data you store into it. Try sending through the data out of the main surface as Amrazek suggested.
Yes now it works.
Anyway, this is the solution:

Uint32 rmask, gmask, bmask, amask;    /* SDL interprets each pixel as a 32-bit number, so our masks must depend       on the endianness (byte order) of the machine */#if SDL_BYTEORDER == SDL_BIG_ENDIAN    rmask = 0xff000000;    gmask = 0x00ff0000;    bmask = 0x0000ff00;    amask = 0x000000ff;#else    rmask = 0x000000ff;    gmask = 0x0000ff00;    bmask = 0x00ff0000;    amask = 0xff000000;#endif	 	SDL_Surface* test;	SDL_Rect *rect = new SDL_Rect();	rect->x=100;	rect->y=100;	rect->w=100;	rect->h=100;	test = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, 200, 200, 32,rmask, gmask, bmask, amask);	Uint32 rectcolor = SDL_MapRGB( test->format, 155, 0, 55 );	//boxRGBA(test,22,33,44,100,144,2,3,122);	SDL_FillRect( test, rect, rectcolor );	CSurface::OnDraw(Surf_Display,test,1,1);


Thanks for the help!

This topic is closed to new replies.

Advertisement