/* * 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; }