/*
* call-seq:
* new(size, depth=0, flags=0) -> Surface
*
* Create and initialize a new Surface object.
*
* A Surface is a grid of image data which you blit (i.e. copy) onto other
* Surfaces. Since the Rubygame display is also a Surface (see the Screen
* class), Surfaces can be blit to the screen; this is the most common way
* to display images on the screen.
*
* Currently, you must create a display window (see Screen#set_mode) before
* creating a new Surface.
*
* This function takes these arguments:
* size:: requested surface size; an array of the form [width, height].
* depth:: requested color depth (in bits per pixel). If depth is 0 (default),
* use the color depth of the current Screen mode.
*--
* automatically choose a color depth: either the depth of the Screen
* mode (if one has been set), or the greatest color depth available
* on the system.
*++
* flags:: an Array or Bitwise-OR'd list of zero or more of the following
* flags (located in the Rubygame module, e.g. Rubygame::SWSURFACE).
* This argument may be omitted, in which case the Surface
* will be a normal software surface (this is not necessarily a bad
* thing).
* SWSURFACE:: (default) request a software surface.
* HWSURFACE:: request a hardware-accelerated surface (using a
* graphics card), if available. Creates a software
* surface if hardware surfaces are not available.
* SRCCOLORKEY:: request a colorkeyed surface. #set_colorkey will
* also enable colorkey as needed. For a description
* of colorkeys, see #set_colorkey.
* SRCALPHA:: request an alpha channel. #set_alpha will
* also enable alpha. as needed. For a description
* of alpha, see #alpha.
*/
VALUE rbgm_surface_new(int argc, VALUE *argv, VALUE class)
{
VALUE self;
SDL_Surface *self_surf;
SDL_PixelFormat* pixformat;
Uint32 flags, Rmask, Gmask, Bmask, Amask;
int w, h, depth, counter;
if( SDL_GetVideoSurface() )
{
/* Pixel format is retrieved from the video surface. */
pixformat = (SDL_GetVideoSurface())->format;
}
else
{
rb_raise(eSDLError,"Cannot create Surface before the Screen mode is set!");
/* The following code causes an inexplicable segfault? :( -j */
/* pixformat = SDL_GetVideoInfo()->vfmt; */
}
Rmask = pixformat->Rmask;
Gmask = pixformat->Gmask;
Bmask = pixformat->Bmask;
Amask = pixformat->Amask;
if( (argc > 1) && (argv[1] != Qnil) && (argv[1] != 0) )
{
/* TODO: We might want to check that the requested depth makes sense. */
depth = NUM2INT(argv[1]);
}
else
{
depth = pixformat->BitsPerPixel;
}
/* Get width and height for new surface from argv[0] */
Check_Type(argv[0],T_ARRAY);
if(RARRAY(argv[0])->len >= 2)
{
w = NUM2INT(rb_ary_entry(argv[0],0));
h = NUM2INT(rb_ary_entry(argv[0],1));
}
else
rb_raise(rb_eArgError,"wrong dimensions for Surface size (%d for 2)",\
RARRAY(argv[0])->len);
if(argc > 2 && argv[2] != Qnil)
{
switch( TYPE(argv[2]) ){
case T_ARRAY:;
for(counter=0; counter < RARRAY(argv[2])->len; counter += 1)
{
flags |= NUM2UINT( rb_ary_entry( argv[2],counter ) );
}
break;
case T_FIXNUM:;
flags = NUM2UINT( argv[2] );
break;
default:;
rb_raise(rb_eArgError,"Wrong type for argument `flags' (wanted Fixnum or Array).");
}
}
/* Finally, we can create the new Surface! Or try, anyway... */
self_surf = SDL_CreateRGBSurface(flags,w,h,depth,Rmask,Gmask,Bmask,Amask);
if( self_surf == NULL )
rb_raise(eSDLError,"Could not create new surface: %s",SDL_GetError());
/* Wrap the new surface in a crunchy candy VALUE shell. */
self = Data_Wrap_Struct( cSurface,0,SDL_FreeSurface,self_surf );
/* The default initialize() does nothing, but may be overridden. */
rb_obj_call_init(self,argc,argv);
return self;
}