Class Rubygame::Surface
In: ext/rubygame/rubygame_mixer.c
lib/rubygame/rect.rb
Parent: Object

Surface‘s draw_* methods provide an interface to SDL_gfx‘s functions for drawing colored shapes onto the Surface. Some methods (draw_arc_s) require a minimum SDL_gfx version (at compile time) to exist.

The base methods (e.g. draw_circle), draw the outline of the shape, without any color inside of it.

Most shapes also have an anti-aliased version, denoted by the ‘a’ in its name (e.g. draw_circle_a). These methods draw smooth outlines with no aliasing (pixelated "jaggies"). Please note that anti-aliased drawing methods take longer than their aliased counterparts.

Most shapes also have a solid version, denoted by the ‘s’ in its name (e.g. draw_circle_s). These methods draw the shape as solid, rather than an outline.

At this time, there are no methods to draw shapes which are both filled and anti-aliased. For some shapes, it may be possible to approximate this effect by drawing a filled shape, then an anti-aliased outline in the same position.

Methods

Public Class methods

Searches each directory in Surface.autoload_dirs for a file with the given filename. If it finds that file, loads it and returns a Surface instance. If it doesn‘t find the file, returns nil.

See Rubygame::NamedResource for more information about this functionality.

[Source]

/*
 *  call-seq:
 *    Surface.autoload( filename )  ->  Surface or nil
 *
 *  Searches each directory in Surface.autoload_dirs for a file with
 *  the given filename. If it finds that file, loads it and returns
 *  a Surface instance. If it doesn't find the file, returns nil.
 *
 *  See Rubygame::NamedResource for more information about this
 *  functionality.
 *
 */
VALUE rbgm_image_autoload( VALUE class, VALUE namev )
{
  VALUE pathv = rb_funcall( class, rb_intern("find_file"), 1, namev );

  if( RTEST(pathv) )
  {
    return rbgm_image_load( class, pathv );
  }
  else
  {
    return Qnil;
  }
}

Load an image file from the disk to a Surface. If the image has an alpha channel (e.g. PNG with transparency), the Surface will as well. If the image cannot be loaded (for example if the image format is unsupported), will raise SDLError.

This method is only usable if Rubygame was compiled with the SDL_image library; you can check Rubygame::VERSIONS[:sdl_image] to see if it was.

This method takes this argument:

filename:a string containing the relative or absolute path to the image file. The file must have the proper file extension, as it is used to determine image format.

These formats may be supported, but some may not be available on a particular system.

BMP:"Windows Bitmap" format.
GIF:"Graphics Interchange Format."
JPG:"Independent JPEG Group" format.
LBM:"Linear Bitmap" format (?)
PCX:"PC Paintbrush" format
PNG:"Portable Network Graphics" format.
PNM:"Portable Any Map" format. (i.e., PPM, PGM, or PBM)
TGA:"Truevision TARGA" format.
TIF:"Tagged Image File Format"
XCF:"eXperimental Computing Facility" (GIMP native format).
XPM:"XPixMap" format.

[Source]

/*
 *  call-seq:
 *    Surface.load( filename )  ->  Surface
 *
 *  Load an image file from the disk to a Surface. If the image has an alpha
 *  channel (e.g. PNG with transparency), the Surface will as well. If the
 *  image cannot be loaded (for example if the image format is unsupported),
 *  will raise SDLError.
 *
 *  This method is only usable if Rubygame was compiled with the SDL_image
 *  library; you can check Rubygame::VERSIONS[:sdl_image] to see if it was.
 *
 *  This method takes this argument:
 *  filename:: a string containing the relative or absolute path to the
 *             image file. The file must have the proper file extension,
 *             as it is used to determine image format.
 *
 *  These formats may be supported, but some may not be available on a
 *  particular system.
 *  BMP:: "Windows Bitmap" format.
 *  GIF:: "Graphics Interchange Format."
 *  JPG:: "Independent JPEG Group" format.
 *  LBM:: "Linear Bitmap" format (?)
 *  PCX:: "PC Paintbrush" format
 *  PNG:: "Portable Network Graphics" format.
 *  PNM:: "Portable Any Map" format. (i.e., PPM, PGM, or PBM)
 *  TGA:: "Truevision TARGA" format.
 *  TIF:: "Tagged Image File Format"
 *  XCF:: "eXperimental Computing Facility" (GIMP native format).
 *  XPM:: "XPixMap" format.
 */
VALUE rbgm_image_load( VALUE class, VALUE filename )
{
        char *name;
        SDL_Surface *surf;

        name = StringValuePtr(filename);
        surf = IMG_Load( name );
        if(surf == NULL)
        {
                rb_raise(eSDLError,"Couldn't load image `%s': %s", name, IMG_GetError());
        }
        return Data_Wrap_Struct( cSurface,0,SDL_FreeSurface,surf );
}

Load an image file from memory (in the form of the given data) to a Surface. If the image has an alpha channel (e.g. PNG with transparency), the Surface will as well. If the image cannot be loaded (for example if the image format is unsupported), will raise SDLError.

This method is only usable if Rubygame was compiled with the SDL_image library; you can check Rubygame::VERSIONS[:sdl_image] to see if it was.

This method takes these arguments:

data:a string containing the data for the image, such as IO::read would return.
type:The type of file that the image is (i.e. ‘TGA’). Case is not important. If absent, the library will try to automatically detect the type.

These formats may be supported, but some may not be available on a particular system.

BMP:"Windows Bitmap" format.
GIF:"Graphics Interchange Format."
JPG:"Independent JPEG Group" format.
LBM:"Linear Bitmap" format (?)
PCX:"PC Paintbrush" format
PNG:"Portable Network Graphics" format.
PNM:"Portable Any Map" format. (i.e., PPM, PGM, or PBM)
TGA:"Truevision TARGA" format.
TIF:"Tagged Image File Format"
XCF:"eXperimental Computing Facility" (GIMP native format).
XPM:"XPixMap" format.

[Source]

/*
 *  call-seq:
 *    Surface.load_from_string( data [,type] )  ->  Surface
 *
 *  Load an image file from memory (in the form of the given data) to a Surface.
 *  If the image has an alpha channel (e.g. PNG with transparency), the Surface
 *  will as well. If the image cannot be loaded (for example if the image
 *  format is unsupported), will raise SDLError.
 *
 *  This method is only usable if Rubygame was compiled with the SDL_image
 *  library; you can check Rubygame::VERSIONS[:sdl_image] to see if it was.
 *
 *  This method takes these arguments:
 *  data:: a string containing the data for the image, such as IO::read would
 *         return.
 *  type:: The type of file that the image is (i.e. 'TGA').  Case is not 
 *         important.  If absent, the library will try to automatically
 *         detect the type.
 *
 *  These formats may be supported, but some may not be available on a
 *  particular system.
 *  BMP:: "Windows Bitmap" format.
 *  GIF:: "Graphics Interchange Format."
 *  JPG:: "Independent JPEG Group" format.
 *  LBM:: "Linear Bitmap" format (?)
 *  PCX:: "PC Paintbrush" format
 *  PNG:: "Portable Network Graphics" format.
 *  PNM:: "Portable Any Map" format. (i.e., PPM, PGM, or PBM)
 *  TGA:: "Truevision TARGA" format.
 *  TIF:: "Tagged Image File Format"
 *  XCF:: "eXperimental Computing Facility" (GIMP native format).
 *  XPM:: "XPixMap" format.
 */
VALUE rbgm_image_load_from_string( int argc, VALUE *argv, VALUE obj)
{
        Check_Type(argv[0], T_STRING);
        /* There's probably a better way of using a string as raw data than this,
         * but I don't know it. */
        void *raw = (void *)RSTRING_PTR(argv[0]);
        int len = RSTRING_LEN(argv[0]);
        
        SDL_RWops *rw = SDL_RWFromMem(raw,len);
        
        SDL_Surface *surf;
        if(argc > 1) {
                Check_Type(argv[1], T_STRING);
                surf = IMG_LoadTyped_RW(rw, 1,StringValuePtr(argv[1]));
        } else {
                surf = IMG_Load_RW(rw,1);
        }
        
        if(surf == NULL)
        {
                rb_raise(eSDLError,"Couldn't load image from string: %s", IMG_GetError());
        }
        return Data_Wrap_Struct( cSurface, 0, SDL_FreeSurface, surf);  
}

**NOTE:** This method name is DEPRECATED and will be removed in Rubygame 3.0. Please use the Surface.load instead.

Load an image file from the disk to a Surface. If the image has an alpha channel (e.g. PNG with transparency), the Surface will as well. If the image cannot be loaded (for example if the image format is unsupported), will raise SDLError.

This method is only usable if Rubygame was compiled with the SDL_image library; you can check Rubygame::VERSIONS[:sdl_image] to see if it was.

This method takes this argument:

filename:a string containing the relative or absolute path to the image file. The file must have the proper file extension, as it is used to determine image format.

These formats may be supported, but some may not be available on a particular system.

BMP:"Windows Bitmap" format.
GIF:"Graphics Interchange Format."
JPG:"Independent JPEG Group" format.
LBM:"Linear Bitmap" format (?)
PCX:"PC Paintbrush" format
PNG:"Portable Network Graphics" format.
PNM:"Portable Any Map" format. (i.e., PPM, PGM, or PBM)
TGA:"Truevision TARGA" format.
TIF:"Tagged Image File Format"
XCF:"eXperimental Computing Facility" (GIMP native format).
XPM:"XPixMap" format.

[Source]

/*
 *  call-seq:
 *    Surface.load_image( filename )  ->  Surface
 *
 *  **NOTE:** This method name is DEPRECATED and will be removed in
 *  Rubygame 3.0. Please use the Surface.load instead.
 *
 *  Load an image file from the disk to a Surface. If the image has an alpha
 *  channel (e.g. PNG with transparency), the Surface will as well. If the
 *  image cannot be loaded (for example if the image format is unsupported),
 *  will raise SDLError.
 *
 *  This method is only usable if Rubygame was compiled with the SDL_image
 *  library; you can check Rubygame::VERSIONS[:sdl_image] to see if it was.
 *
 *  This method takes this argument:
 *  filename:: a string containing the relative or absolute path to the
 *             image file. The file must have the proper file extension,
 *             as it is used to determine image format.
 *
 *  These formats may be supported, but some may not be available on a
 *  particular system.
 *  BMP:: "Windows Bitmap" format.
 *  GIF:: "Graphics Interchange Format."
 *  JPG:: "Independent JPEG Group" format.
 *  LBM:: "Linear Bitmap" format (?)
 *  PCX:: "PC Paintbrush" format
 *  PNG:: "Portable Network Graphics" format.
 *  PNM:: "Portable Any Map" format. (i.e., PPM, PGM, or PBM)
 *  TGA:: "Truevision TARGA" format.
 *  TIF:: "Tagged Image File Format"
 *  XCF:: "eXperimental Computing Facility" (GIMP native format).
 *  XPM:: "XPixMap" format.
 */
VALUE rbgm_image_load_image( VALUE class, VALUE filename )
{

  /* This feature will be removed in Rubygame 3.0. */
  rg_deprecated("Rubygame::Surface.load_image", "3.0");

        char *name;
        SDL_Surface *surf;

        name = StringValuePtr(filename);
        surf = IMG_Load( name );
        if(surf == NULL)
        {
                rb_raise(eSDLError,"Couldn't load image `%s': %s", name, IMG_GetError());
        }
        return Data_Wrap_Struct( cSurface,0,SDL_FreeSurface,surf );
}

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.

This method may raise SDLError if the SDL video subsystem could not be initialized for some reason.

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), 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.

[Source]

/* 
 *  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.
 *
 *  This method may raise SDLError if the SDL video subsystem could
 *  not be initialized for some reason.
 *
 *  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),
 *          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;
        VALUE vsize, vdepth, vflags;

        rb_scan_args(argc, argv, "12", &vsize, &vdepth, &vflags);

        if( SDL_GetVideoSurface() )
        {
                /* Pixel format is retrieved from the video surface. */
                pixformat = (SDL_GetVideoSurface())->format;
        }
        else
        {
                /* We can only get the system color depth when the video system
                 * has been initialized. */
                if( init_video_system() == 0 )
                {
                        pixformat = SDL_GetVideoInfo()->vfmt;
                }
                else
                {
                        rb_raise(eSDLError,"Could not initialize SDL video subsystem.");
                        return Qnil;
                }
        }

        Rmask = pixformat->Rmask;
        Gmask = pixformat->Gmask;
        Bmask = pixformat->Bmask;
        Amask = pixformat->Amask;

        if( !NIL_P(vdepth) && NUM2INT(vdepth) > 0 )
        {
                /* TODO: We might want to check that the requested depth makes sense. */
                depth = NUM2INT(vdepth);
        }
        else
        {
                depth = pixformat->BitsPerPixel;
        }
                

        /* Get width and height for new surface from vsize */
        vsize = convert_to_array(vsize);

        if(RARRAY_LEN(vsize) >= 2)
        {
                w = NUM2INT(rb_ary_entry(vsize,0));
                h = NUM2INT(rb_ary_entry(vsize,1));
        }
        else
                rb_raise(rb_eArgError,"Array is too short for Surface size (%d for 2)",\
                        RARRAY_LEN(vsize));
        
        flags = collapse_flags(vflags); /* in rubygame_shared */

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

Return the dimensions of the surface that would be returned if rotozoom() were called on a Surface of the given size, with the same angle and zoom factors.

If Rubygame was compiled with SDL_gfx-2.0.13 or greater, zoom can be an Array of 2 Numerics for separate X and Y scaling. Also, it can be negative to indicate flipping horizontally or vertically.

Will return nil if you attempt to use separate X and Y zoom factors or negative zoom factors with an unsupported version of SDL_gfx.

This method takes these arguments:

size:an Array with the hypothetical Surface width and height (pixels)
angle:degrees to rotate counter-clockwise (negative for clockwise).
zoom:scaling factor(s). A single positive Numeric, unless you have SDL_gfx-2.0.13 or greater (see above).

[Source]

/*
 *  call-seq:
 *    rotozoom_size( size, angle, zoom )  ->  [width, height] or nil
 *
 *  Return the dimensions of the surface that would be returned if
 *  #rotozoom() were called on a Surface of the given size, with
 *  the same angle and zoom factors.
 *
 *  If Rubygame was compiled with SDL_gfx-2.0.13 or greater, +zoom+ can be
 *  an Array of 2 Numerics for separate X and Y scaling. Also, it can be
 *  negative to indicate flipping horizontally or vertically.
 *
 *  Will return +nil+ if you attempt to use separate X and Y zoom factors
 *  or negative zoom factors with an unsupported version of SDL_gfx.
 *
 *  This method takes these arguments:
 *  size::  an Array with the hypothetical Surface width and height (pixels)
 *  angle:: degrees to rotate counter-clockwise (negative for clockwise).
 *  zoom::  scaling factor(s). A single positive Numeric, unless you have
 *          SDL_gfx-2.0.13 or greater (see above).
 */
VALUE rbgm_transform_rzsize(int argc, VALUE *argv, VALUE module)
{
  int w,h, dstw,dsth;
  double angle, zoomx, zoomy;

  VALUE vsize, vangle, vzoom;

  rb_scan_args(argc,argv,"3", &vsize, &vangle, &vzoom);

  vsize = convert_to_array(vsize);
  w = NUM2INT(rb_ary_entry(argv[0],0));
  h = NUM2INT(rb_ary_entry(argv[0],0));
  angle = NUM2DBL(vangle);

  switch( TYPE(vzoom) )
  {
    case T_ARRAY: {
      /* Separate X/Y rotozoom scaling was not supported prior to 2.0.13. */
      /* Check if we have at least version 2.0.13 of SDL_gfxPrimitives */
#ifdef HAVE_ROTOZOOMXY
      /* Do the real function. */
      zoomx = NUM2DBL(rb_ary_entry(vzoom,0));
      zoomy = NUM2DBL(rb_ary_entry(vzoom,1));
      rotozoomSurfaceSizeXY(w, h, angle, zoomx, zoomy, &dstw, &dsth);
#else 
      /* Return nil, because it's not supported. */
      return Qnil;
#endif
      break;
    }

    case T_FLOAT:
    case T_FIXNUM: {
      zoomx = NUM2DBL(argv[1]);
#ifndef HAVE_ROTOZOOMXY
      if(zoomx < 0)                /* negative zoom (for flipping) */
      {
        /* Return nil, because it's not supported. */
        return Qnil;
      }
#endif
      rotozoomSurfaceSize(w, h, angle, zoomx, &dstw, &dsth);
      break;
    }

    default: {
      rb_raise(rb_eArgError,
               "wrong zoom factor type (expected Array or Numeric)");
      break;
    }

  }

  /*   if(dstw == NULL || dsth == NULL)
       rb_raise(eSDLError,"Could not rotozoom surface: %s",SDL_GetError());*/
  return rb_ary_new3(2,INT2NUM(dstw),INT2NUM(dsth));

}

Return the dimensions of the surface that would be returned if zoom were called with a surface of the given size and zoom factors.

This method takes these arguments:

size:an Array with the hypothetical surface width and height (pixels)
zoom:the factor to scale by in both x and y directions, or an Array with separate x and y scale factors.

[Source]

/* 
 *  call-seq:
 *    zoom_size(size, zoom)  ->  [width, height]
 *
 *  Return the dimensions of the surface that would be returned if
 *  #zoom were called with a surface of the given size and zoom factors.
 *
 *  This method takes these arguments:
 *  size:: an Array with the hypothetical surface width and height (pixels)
 *  zoom:: the factor to scale by in both x and y directions, or an Array
 *         with separate x and y scale factors.
 */
VALUE rbgm_transform_zoomsize(int argc, VALUE *argv, VALUE module)
{
  int w,h, dstw,dsth;
  double zoomx, zoomy;

  VALUE vsize, vzoom;

  rb_scan_args(argc,argv,"2", &vsize, &vzoom);

  vsize = convert_to_array(vsize);
  w = NUM2INT(rb_ary_entry(vsize,0));
  h = NUM2INT(rb_ary_entry(vsize,1));

  switch( TYPE(vzoom) )
  {
    case T_ARRAY: {
      zoomx = NUM2DBL(rb_ary_entry(vzoom,0));
      zoomy = NUM2DBL(rb_ary_entry(vzoom,1));
      break;
    }

    case T_FLOAT:
    case T_FIXNUM: {
      zoomx = NUM2DBL(vzoom);
      zoomy = zoomx;
      break;
    }
    default: {
      rb_raise(rb_eArgError,
               "wrong zoom factor type (expected Array or Numeric)");
      break;
    }
  }

  zoomSurfaceSize(w, h,  zoomx, zoomy, &dstw, &dsth);
  return rb_ary_new3(2,INT2NUM(dstw),INT2NUM(dsth));
}

Public Instance methods

Return the per-surface alpha (opacity; non-transparency) of the surface. It can range from 0 (full transparent) to 255 (full opaque).

[Source]

/* 
 *  call-seq:
 *     alpha
 *
 *  Return the per-surface alpha (opacity; non-transparency) of the surface.
 *  It can range from 0 (full transparent) to 255 (full opaque).
 */
VALUE rbgm_surface_get_alpha(VALUE self)
{
        SDL_Surface *surf;
        Data_Get_Struct(self, SDL_Surface, surf);
        return INT2NUM(surf->format->alpha);
}

Blit (copy) all or part of the surface‘s image to another surface, at a given position. Returns a Rect representing the area of target which was affected by the blit.

This method takes these arguments:

target:the target Surface on which to paste the image.
dest:the coordinates of the top-left corner of the blit. Affects the area of other the image data is /pasted/ over. Can also be a Rect or an Array larger than 2, but width and height will be ignored.
source:a Rect representing the area of the source surface to get data from. Affects where the image data is /copied/ from. Can also be an Array of no less than 4 values.

[Source]

/* 
 *  call-seq:
 *     blit(target,dest,source=nil)  ->  Rect
 *
 *  Blit (copy) all or part of the surface's image to another surface,
 *  at a given position. Returns a Rect representing the area of 
 *  +target+ which was affected by the blit.
 *
 *  This method takes these arguments:
 *  target:: the target Surface on which to paste the image.
 *  dest::   the coordinates of the top-left corner of the blit. Affects the
 *           area of +other+ the image data is /pasted/ over.
 *           Can also be a Rect or an Array larger than 2, but
 *           width and height will be ignored. 
 *  source:: a Rect representing the area of the source surface to get data
 *           from. Affects where the image data is /copied/ from.
 *           Can also be an Array of no less than 4 values. 
 */
VALUE rbgm_surface_blit(int argc, VALUE *argv, VALUE self)
{
        int left, top, right, bottom;
        int blit_x,blit_y,blit_w,blit_h;
        //int dest_x,dest_y,dest_w,dest_h;
        int src_x,src_y,src_w,src_h;
        VALUE returnrect;
        SDL_Surface *src, *dest;
        SDL_Rect *src_rect, *blit_rect;

        VALUE vtarget, vdest, vsource;

        rb_scan_args( argc, argv, "21", &vtarget, &vdest, &vsource );

        Data_Get_Struct(self, SDL_Surface, src);
        Data_Get_Struct(vtarget, SDL_Surface, dest);

        vdest = convert_to_array(vdest);
        blit_x = NUM2INT(rb_ary_entry(vdest,0));
        blit_y = NUM2INT(rb_ary_entry(vdest,1));

        /* did we get a src_rect argument or not? */
        if( !NIL_P(vsource) )
        {
                /* it might be good to check that it's actually a rect */
                vsource = convert_to_array(vsource);
                src_x = NUM2INT( rb_ary_entry(vsource,0) );
                src_y = NUM2INT( rb_ary_entry(vsource,1) );
                src_w = NUM2INT( rb_ary_entry(vsource,2) );
                src_h = NUM2INT( rb_ary_entry(vsource,3) );
        }
        else
        {
                src_x = 0;
                src_y = 0;
                src_w = src->w;
                src_h = src->h;
        }
        src_rect = make_rect( src_x, src_y, src_w, src_h );

        /* experimental (broken) rectangle cropping code */
        /* crop if it went off left/top/right/bottom */
        //left = max(blit_x,0);
        //top = max(blit_y,0);
        //right = min(blit_x+src_w,dest->w);
        //bottom = min(blit_y+src_h,dest->h);

        left = blit_x;
        top = blit_y;
        right = blit_x+src_w;
        bottom = blit_y+src_h;
                
        //blit_w = min(blit_x+blit_w,dest->w) - max(blit_x,0);
        //blit_h = min(blit_y+blit_h,dest->h) - max(blit_y,0);
        blit_w = right - left;
        blit_h = bottom - top;
        
        blit_rect = make_rect( left, top, blit_w, blit_h );

        SDL_BlitSurface(src,src_rect,dest,blit_rect);

        returnrect = rb_funcall(cRect,rb_intern("new"),4,
                                INT2NUM(left),INT2NUM(top),\
                                INT2NUM(blit_w),INT2NUM(blit_h));

        free(blit_rect);
        free(src_rect);
        return returnrect;
}

Return the clipping area for this Surface. See also cliprect=.

The clipping area of a Surface is the only part which can be drawn upon by other Surface‘s blits. By default, the clipping area is the entire area of the Surface.

[Source]

/*
 *  call-seq:
 *    clip  ->  Rect
 *
 *  Return the clipping area for this Surface. See also #cliprect=.
 *
 *  The clipping area of a Surface is the only part which can be drawn upon
 *  by other Surface's #blits. By default, the clipping area is the entire area
 *  of the Surface.
 */
VALUE rbgm_surface_get_clip( VALUE self )
{
        SDL_Rect rect;
        SDL_Surface *surf;
        Data_Get_Struct(self, SDL_Surface, surf);

        SDL_GetClipRect(surf, &rect);

        return rb_funcall(cRect,rb_intern("new"),4,
                          INT2NUM(rect.x),INT2NUM(rect.y),
                          INT2NUM(rect.w),INT2NUM(rect.h));
}

Set the current clipping area of the Surface. See also cliprect.

The clipping area of a Surface is the only part which can be drawn upon by other Surface‘s blits. The clipping area will be clipped to the edges of the surface so that the clipping area for a Surface can never fall outside the edges of the Surface.

By default, the clipping area is the entire area of the Surface. You may set clip to nil, which will reset the clipping area to cover the entire Surface.

[Source]

/*
 *  call-seq:
 *    clip = Rect or nil
 *
 *  Set the current clipping area of the Surface. See also #cliprect.
 *
 *  The clipping area of a Surface is the only part which can be drawn upon
 *  by other Surface's #blits. The clipping area will be clipped to the edges
 *  of the surface so that the clipping area for a Surface can never fall
 *  outside the edges of the Surface.
 *
 *  By default, the clipping area is the entire area of the Surface.
 *  You may set clip to +nil+, which will reset the clipping area to cover
 *  the entire Surface.
 */
VALUE rbgm_surface_set_clip( VALUE self, VALUE clip )
{
        SDL_Rect *rect;
        SDL_Surface *surf;
        Data_Get_Struct(self, SDL_Surface, surf);


        if( NIL_P(clip) )
        {
                SDL_SetClipRect(surf,NULL);
        }
        else
        { 
                clip = convert_to_array(clip);
                rect = make_rect(\
                                 NUM2INT(rb_ary_entry(clip,0)),\
                                 NUM2INT(rb_ary_entry(clip,1)),\
                                 NUM2INT(rb_ary_entry(clip,2)),\
                                 NUM2INT(rb_ary_entry(clip,3))\
                                 );

                SDL_SetClipRect(surf,rect);
                free(rect);
        }

        return self;
}

Return the colorkey of the surface in the form [r,g,b] (or nil if there is no key). The colorkey of a surface is the exact color which will be ignored when the surface is blitted, effectively turning that color transparent. This is often used to make a blue (for example) background on an image seem transparent.

[Source]

/*
 *  call-seq:
 *     colorkey  ->  [r,g,b]  or  nil
 *
 *  Return the colorkey of the surface in the form [r,g,b] (or +nil+ if there
 *  is no key). The colorkey of a surface is the exact color which will be
 *  ignored when the surface is blitted, effectively turning that color
 *  transparent. This is often used to make a blue (for example) background
 *  on an image seem transparent.
 */
VALUE rbgm_surface_get_colorkey( VALUE self )
{
        SDL_Surface *surf;
        Uint32 colorkey;
        Uint8 r,g,b;

        Data_Get_Struct(self, SDL_Surface, surf);
        colorkey = surf->format->colorkey;

        if( surf->flags & SDL_SRCCOLORKEY )
        {
                SDL_GetRGB(colorkey, surf->format, &r, &g, &b);
                return rb_ary_new3(3,UINT2NUM(r),UINT2NUM(g),UINT2NUM(b));
        }
        else
        {
                /* No colorkey set. */
                return Qnil;
        }

}

Copies the Surface to a new Surface with the pixel format of another Surface, for fast blitting. May raise SDLError if a problem occurs.

This method takes these arguments:

  • other:: The Surface to match pixel format against. If nil, the
             display surface (i.e. Screen) is used, if available; if no
             display surface is available, raises SDLError.
    
  • flags:: An array of flags to pass when the new Surface is created.
             See Surface#new.
    

[Source]

/* 
 *  call-seq:
 *    convert( other=nil, flags=nil )  ->  Surface
 *
 *  Copies the Surface to a new Surface with the pixel format of another
 *  Surface, for fast blitting. May raise SDLError if a problem occurs.
 *
 *  This method takes these arguments:
 *  - other::  The Surface to match pixel format against. If +nil+, the
 *             display surface (i.e. Screen) is used, if available; if no
 *             display surface is available, raises SDLError.
 *  - flags::  An array of flags to pass when the new Surface is created.
 *             See Surface#new.
 *
 */
VALUE rbgm_surface_convert(int argc, VALUE *argv, VALUE self)
{
        SDL_Surface *surf, *othersurf, *newsurf;
  Uint32 flags = 0;
        VALUE vother, vflags;

        Data_Get_Struct(self, SDL_Surface, surf);

        rb_scan_args(argc, argv, "02", &vother, &vflags );

        if( !NIL_P(vother) )
  {
    Data_Get_Struct(vother, SDL_Surface, othersurf);
  }
  else
  {
    othersurf = SDL_GetVideoSurface();
    if( othersurf == NULL )
    {
      rb_raise(eSDLError, "Cannot convert Surface with no target given and no Screen made: %s", SDL_GetError());
    }
  }

        flags = collapse_flags(vflags); /* in rubygame_shared.c */

  if( init_video_system() == 0 )
  {
    newsurf = SDL_ConvertSurface( surf, othersurf->format, flags );
  }
  else
  {
    newsurf = NULL;
  }

  if( newsurf == NULL )
  {
    rb_raise(eSDLError,\
             "Could not convert the Surface: %s",\
             SDL_GetError());
  }

  return Data_Wrap_Struct( cSurface,0,SDL_FreeSurface,newsurf );  
}

Return the color depth (in bits per pixel) of the surface.

[Source]

/*  call-seq:
 *     depth
 *
 * Return the color depth (in bits per pixel) of the surface.
 */
VALUE rbgm_surface_get_depth(VALUE self)
{
        SDL_Surface *surf;
        Data_Get_Struct(self, SDL_Surface, surf);
        return UINT2NUM(surf->format->BitsPerPixel);
}

Draw a non-solid arc (part of a circle), given the coordinates of its center, radius, and starting/ending angles. See also draw_arc_s

*IMPORTANT:* This method will only be defined if Rubygame was compiled with SDL_gfx-2.0.11 or greater. (Note: draw_arc_s does not have this requirement.)

This method takes these arguments:

center:the coordinates of circle‘s center, [x,y].
radius:the radius (pixels) of the circle.
angles:the start and end angles (in degrees) of the arc, [start,end]. Angles are given CLOCKWISE from the positive x (remember that the positive Y direction is down, rather than up).
color:the color of the shape, [r,g,b,a]. If alpha is omitted, it is drawn at full opacity.

[Source]

/* 
 *  call-seq:
 *    draw_arc(center, radius, angles, color)
 *
 *  Draw a non-solid arc (part of a circle), given the coordinates of
 *  its center, radius, and starting/ending angles.
 *  See also #draw_arc_s
 *
 *  *IMPORTANT:* This method will only be defined if Rubygame was compiled
 *  with SDL_gfx-2.0.11 or greater. (Note: #draw_arc_s does not have
 *  this requirement.)
 *
 *  This method takes these arguments:
 *  center::  the coordinates of circle's center, [x,y].
 *  radius::  the radius (pixels) of the circle.
 *  angles::  the start and end angles (in degrees) of the arc, [start,end].
 *            Angles are given *CLOCKWISE* from the positive x
 *            (remember that the positive Y direction is down, rather than up).
 *  color::   the color of the shape, [r,g,b,a]. If alpha
 *            is omitted, it is drawn at full opacity.
 */
VALUE rbgm_draw_pie(VALUE target, VALUE center, VALUE radius, VALUE angles, VALUE rgba)
{
#ifdef HAVE_NONFILLEDPIE
  draw_pie(target,center,radius,angles,rgba,0); /* no fill */
  return target;
#else
  return Qnil;
#endif
}

Like draw_arc, but the shape is solid, instead an outline. (This method does not require SDL_gfx 2.0.11 or greater, but draw_arc does.)

[Source]

/* 
 *  call-seq:
 *    draw_arc_s(center, radius, angles, color)
 *
 * Like #draw_arc, but the shape is solid, instead an outline.
 * (This method does not require SDL_gfx 2.0.11 or greater, 
 * but #draw_arc does.)
 */
VALUE rbgm_draw_fillpie(VALUE target, VALUE center, VALUE radius, VALUE angles, VALUE rgba)
{
  draw_pie(target,center,radius,angles,rgba,1); /* fill */
  return target;
}

Draw a non-solid box (rectangle) on the Surface, given the coordinates of its top-left corner and bottom-right corner. See also draw_box_s

This method takes these arguments:

point1:the coordinates of top-left corner, [x1,y1].
point2:the coordinates of bottom-right corner, [x2,y2].
color:the color of the shape, [r,g,b,a]. If alpha is omitted, it is drawn at full opacity.

[Source]

/*  call-seq:
 *    draw_box(point1, point2, color)
 *
 *  Draw a non-solid box (rectangle) on the Surface, given the coordinates of
 *  its top-left corner and bottom-right corner. See also #draw_box_s
 *
 *  This method takes these arguments:
 *  point1::  the coordinates of top-left corner, [x1,y1].
 *  point2::  the coordinates of bottom-right corner, [x2,y2].
 *  color::   the color of the shape, [r,g,b,a]. If alpha
 *            is omitted, it is drawn at full opacity.
 */
VALUE rbgm_draw_rect(VALUE target, VALUE pt1, VALUE pt2, VALUE rgba)
{
  draw_rect(target,pt1,pt2,rgba,0); /* no fill */
  return target;
}

Like draw_box, but the shape is solid, instead of an outline. (You may find using fill to be more convenient and perhaps faster than this method.)

[Source]

/*  call-seq:
 *    draw_box_s(point1, point2, color)
 *
 *  Like #draw_box, but the shape is solid, instead of an outline.
 *  (You may find using #fill to be more convenient and perhaps faster than
 *  this method.)
 */
VALUE rbgm_draw_fillrect(VALUE target, VALUE pt1, VALUE pt2, VALUE rgba)
{
  draw_rect(target,pt1,pt2,rgba,1); /* fill */
  return target;
}

Draw a non-solid circle on the Surface, given the coordinates of its center and its radius. See also draw_circle_a and draw_circle_s

This method takes these arguments:

center:the coordinates of circle‘s center, [x,y].
radius:the radius (pixels) of the circle.
color:the color of the shape, [r,g,b,a]. If alpha is omitted, it is drawn at full opacity.

[Source]

/* 
 *  call-seq:
 *    draw_circle(center, radius, color)
 *
 *  Draw a non-solid circle on the Surface, given the coordinates of its
 *  center and its radius. See also #draw_circle_a and #draw_circle_s
 *
 *  This method takes these arguments:
 *  center::  the coordinates of circle's center, [x,y].
 *  radius::  the radius (pixels) of the circle.
 *  color::   the color of the shape, [r,g,b,a]. If alpha
 *            is omitted, it is drawn at full opacity.
 */
VALUE rbgm_draw_circle(VALUE target, VALUE center, VALUE radius, VALUE rgba)
{
  draw_circle(target,center,radius,rgba,0,0); /* no aa, no fill */
  return target;
}

Like draw_circle, but the outline is anti-aliased.

[Source]

/* 
 *  call-seq:
 *    draw_circle_a(center, radius, color)
 *
 *  Like #draw_circle, but the outline is anti-aliased.
 */
VALUE rbgm_draw_aacircle(VALUE target, VALUE center, VALUE radius, VALUE rgba)
{
  draw_circle(target,center,radius,rgba,1,0); /* aa, no fill */
  return target;
}

Like draw_circle, but the shape is solid, instead of an outline.

[Source]

/* 
 *  call-seq:
 *    draw_circle_s(center, radius, color)
 *
 *  Like #draw_circle, but the shape is solid, instead of an outline.
 */
VALUE rbgm_draw_fillcircle(VALUE target, VALUE center, VALUE radius, VALUE rgba)
{
  draw_circle(target,center,radius,rgba,0,1); /* no aa, fill */
  return target;
}

Draw a non-solid ellipse (oval) on the Surface, given the coordinates of its center and its horizontal and vertical radii. See also draw_ellipse_a and draw_ellipse_s

This method takes these arguments:

center:the coordinates of ellipse‘s center, [x,y].
radii:the x and y radii (pixels), [rx,ry].
color:the color of the shape, [r,g,b,a]. If alpha is omitted, it is drawn at full opacity.

[Source]

/* 
 *  call-seq:
 *    draw_ellipse(center, radius, color)
 *
 *  Draw a non-solid ellipse (oval) on the Surface, given the 
 *  coordinates of its center and its horizontal and vertical radii.
 *  See also #draw_ellipse_a and #draw_ellipse_s
 *
 *  This method takes these arguments:
 *  center::  the coordinates of ellipse's center, [x,y].
 *  radii::   the x and y radii (pixels), [rx,ry].
 *  color::   the color of the shape, [r,g,b,a]. If alpha
 *            is omitted, it is drawn at full opacity.
 */
VALUE rbgm_draw_ellipse(VALUE target, VALUE center, VALUE radii, VALUE rgba)
{
  draw_ellipse(target,center,radii,rgba,0,0); /* no aa, no fill */
  return target;
}

Like draw_ellipse, but the ellipse border is anti-aliased.

[Source]

/* 
 *  call-seq:
 *    draw_ellipse_a(center, radius, color)
 *
 *  Like #draw_ellipse, but the ellipse border is anti-aliased.
 */
VALUE rbgm_draw_aaellipse(VALUE target, VALUE center, VALUE radii, VALUE rgba)
{
  draw_ellipse(target,center,radii,rgba,1,0); /* aa, no fill */
  return target;
}

Like draw_ellipse, but the shape is solid, instead of an outline.

[Source]

/* 
 *  call-seq:
 *    draw_ellipse_s(center, radius, color)
 *
 *  Like #draw_ellipse, but the shape is solid, instead of an outline.
 */
VALUE rbgm_draw_fillellipse(VALUE target, VALUE center, VALUE radii, VALUE rgba)
{
  draw_ellipse(target,center,radii,rgba,0,1); /* no aa, fill */
  return target;
}

Draw a line segment between two points on the Surface. See also draw_line_a

This method takes these arguments:

point1:the coordinates of one end of the line, [x1,y1].
point2:the coordinates of the other end of the line, [x2,y2].
color:the color of the shape, [r,g,b,a]. If alpha is omitted, it is drawn at full opacity.

[Source]

/*  call-seq:
 *    draw_line(point1, point2, color)
 *
 *  Draw a line segment between two points on the Surface.
 *  See also #draw_line_a
 *
 *  This method takes these arguments:
 *  point1::  the coordinates of one end of the line, [x1,y1].
 *  point2::  the coordinates of the other end of the line, [x2,y2].
 *  color::   the color of the shape, [r,g,b,a]. If alpha
 *            is omitted, it is drawn at full opacity.
 */
VALUE rbgm_draw_line(VALUE target, VALUE pt1, VALUE pt2, VALUE rgba)
{
  draw_line(target,pt1,pt2,rgba,0); /* no anti-aliasing */
  return target;
}

Like draw_line, but the line will be anti-aliased.

[Source]

/*  call-seq:
 *    draw_line_a(point1, point2, color)
 *
 *  Like #draw_line, but the line will be anti-aliased.
 */
VALUE rbgm_draw_aaline(VALUE target, VALUE pt1, VALUE pt2, VALUE rgba)
{
  draw_line(target,pt1,pt2,rgba,1); /* anti-aliasing */
  return target;
}

Draw a non-solid polygon, given the coordinates of its vertices, in the order that they are connected. This is essentially a series of connected dots. See also draw_polygon_a and draw_polygon_s.

This method takes these arguments:

points:an Array containing the coordinate pairs for each vertex of the polygon, in the order that they are connected, e.g. [ [x1,y1], [x2,y2], …, [xn,yn] ]. To draw a closed shape, the final coordinate pair should match the first.
color:the color of the shape, [r,g,b,a]. If alpha is omitted, it is drawn at full opacity.

[Source]

/* 
 *  call-seq:
 *    draw_polygon(points, color)
 *
 *  Draw a non-solid polygon, given the coordinates of its vertices, in the
 *  order that they are connected. This is essentially a series of connected
 *  dots. See also #draw_polygon_a and #draw_polygon_s.
 *
 *  This method takes these arguments:
 *  points::  an Array containing the coordinate pairs for each vertex of the
 *            polygon, in the order that they are connected, e.g.
 *            <tt>[ [x1,y1], [x2,y2], ..., [xn,yn] ]</tt>. To draw a closed 
 *            shape, the final coordinate pair should match the first.
 *  color::   the color of the shape, [r,g,b,a]. If alpha
 *            is omitted, it is drawn at full opacity.
 */
VALUE rbgm_draw_polygon(VALUE target, VALUE points, VALUE rgba)
{
  draw_polygon(target,points,rgba,0,0); /* no aa, no fill */
  return target;
}

Like draw_polygon, but the lines are anti-aliased.

[Source]

/* 
 *  call-seq:
 *    draw_polygon_a(points, color)
 *
 *  Like #draw_polygon, but the lines are anti-aliased.
 */
VALUE rbgm_draw_aapolygon(VALUE target, VALUE points, VALUE rgba)
{
  draw_polygon(target,points,rgba,1,0); /* aa, no fill */
  return target;
}

Like draw_polygon, but the shape is solid, not an outline.

[Source]

/* 
 *  call-seq:
 *    draw_polygon_s(points, color)
 *
 *  Like #draw_polygon, but the shape is solid, not an outline.
 */
VALUE rbgm_draw_fillpolygon(VALUE target, VALUE points, VALUE rgba)
{
  draw_polygon(target,points,rgba,0,1); /* no aa, fill */
  return target;
}

Fill all or part of a Surface with a color.

This method takes these arguments:

color:color to fill with, in the form +[r,g,b]+ or +[r,g,b,a]+ (for partially transparent fills).
rect:a Rubygame::Rect representing the area of the surface to fill with color. Omit to fill the entire surface.

[Source]

/* 
 *  call-seq:
 *     fill(color,rect=nil)
 *
 *  Fill all or part of a Surface with a color.
 *
 *  This method takes these arguments:
 *  color:: color to fill with, in the form +[r,g,b]+ or +[r,g,b,a]+ (for
 *          partially transparent fills).
 *  rect::  a Rubygame::Rect representing the area of the surface to fill
 *          with color. Omit to fill the entire surface.
 */
VALUE rbgm_surface_fill( int argc, VALUE *argv, VALUE self )
{
        SDL_Surface *surf;
        SDL_Rect *rect;
        Uint32 color;
        Uint8 r,g,b,a;
        VALUE vcolor, vrect;

        Data_Get_Struct(self, SDL_Surface, surf);

        rb_scan_args(argc, argv, "11", &vcolor, &vrect);

        vcolor = convert_color(vcolor);
        extract_rgba_u8_as_u8(vcolor, &r, &g, &b, &a);
        color = SDL_MapRGBA(surf->format, r,g,b,a);

        if( NIL_P(vrect) )
        {
                SDL_FillRect(surf,NULL,color);
        }
        else
        {
                vrect = convert_to_array(vrect);

                rect = make_rect(\
                                                                                 NUM2INT(rb_ary_entry(vrect,0)),\
                                                                                 NUM2INT(rb_ary_entry(vrect,1)),\
                                                                                 NUM2INT(rb_ary_entry(vrect,2)),\
                                                                                 NUM2INT(rb_ary_entry(vrect,3))\
                                                                                 );
                SDL_FillRect(surf,rect,color);
                free(rect);
        }

        return self;
}

Return any flags the surface was initialized with (as a bitwise OR‘d integer).

[Source]

/*  call-seq:
 *     flags
 *
 *  Return any flags the surface was initialized with 
 *  (as a bitwise OR'd integer).
 */
VALUE rbgm_surface_get_flags(VALUE self)
{
        SDL_Surface *surf;
        Data_Get_Struct(self, SDL_Surface, surf);
        return UINT2NUM(surf->flags);
}

Flips the source surface horizontally (if horz is true), vertically (if vert is true), or both (if both are true). This operation is non-destructive; the original image can be perfectly reconstructed by flipping the resultant image again.

This operation does NOT require SDL_gfx.

A similar effect can (supposedly) be achieved by giving X or Y zoom factors of -1 to rotozoom (only if compiled with SDL_gfx 2.0.13 or greater). Your mileage may vary.

[Source]

/* 
 * call-seq:
 *    flip(horz, vert)  ->  Surface
 * 
 *  Flips the source surface horizontally (if +horz+ is true), vertically
 *  (if +vert+ is true), or both (if both are true). This operation is
 *  non-destructive; the original image can be perfectly reconstructed by
 *  flipping the resultant image again.
 *
 *  This operation does NOT require SDL_gfx.
 *
 *  A similar effect can (supposedly) be achieved by giving X or Y zoom
 *  factors of -1 to #rotozoom (only if compiled with SDL_gfx 2.0.13 or
 *  greater). Your mileage may vary.
 */
VALUE rbgm_transform_flip(VALUE self, VALUE vhorz, VALUE vvert)
{
  SDL_Surface *surf, *newsurf;
  int xaxis, yaxis;

  int loopx, loopy;
  int pixsize, srcpitch, dstpitch;
  Uint8 *srcpix, *dstpix;

  xaxis = RTEST(vhorz);
  yaxis = RTEST(vvert);

  Data_Get_Struct(self,SDL_Surface,surf);

  /* Borrowed from Pygame: */
  newsurf = newsurf_fromsurf(surf, surf->w, surf->h);
  if(!newsurf)
    return Qnil;

  pixsize = surf->format->BytesPerPixel;
  srcpitch = surf->pitch;
  dstpitch = newsurf->pitch;

  SDL_LockSurface(newsurf);

  srcpix = (Uint8*)surf->pixels;
  dstpix = (Uint8*)newsurf->pixels;

  if(!xaxis)
  {
    if(!yaxis)
    {
      for(loopy = 0; loopy < surf->h; ++loopy)
        memcpy(dstpix+loopy*dstpitch, srcpix+loopy*srcpitch, surf->w*surf->format->BytesPerPixel);
    }
    else
    {
      for(loopy = 0; loopy < surf->h; ++loopy)
        memcpy(dstpix+loopy*dstpitch, srcpix+(surf->h-1-loopy)*srcpitch, surf->w*surf->format->BytesPerPixel);
    }
  }
  else /*if (xaxis)*/
  {
    if(yaxis)
    {
      switch(surf->format->BytesPerPixel)
      {
      case 1:
        for(loopy = 0; loopy < surf->h; ++loopy) {
          Uint8* dst = (Uint8*)(dstpix+loopy*dstpitch);
          Uint8* src = ((Uint8*)(srcpix+(surf->h-1-loopy)*srcpitch)) + surf->w - 1;
          for(loopx = 0; loopx < surf->w; ++loopx)
            *dst++ = *src--;
        }break;
      case 2:
        for(loopy = 0; loopy < surf->h; ++loopy) {
          Uint16* dst = (Uint16*)(dstpix+loopy*dstpitch);
          Uint16* src = ((Uint16*)(srcpix+(surf->h-1-loopy)*srcpitch)) + surf->w - 1;
          for(loopx = 0; loopx < surf->w; ++loopx)
            *dst++ = *src--;
        }break;
      case 4:
        for(loopy = 0; loopy < surf->h; ++loopy) {
          Uint32* dst = (Uint32*)(dstpix+loopy*dstpitch);
          Uint32* src = ((Uint32*)(srcpix+(surf->h-1-loopy)*srcpitch)) + surf->w - 1;
          for(loopx = 0; loopx < surf->w; ++loopx)
            *dst++ = *src--;
        }break;
      case 3:
        for(loopy = 0; loopy < surf->h; ++loopy) {
          Uint8* dst = (Uint8*)(dstpix+loopy*dstpitch);
          Uint8* src = ((Uint8*)(srcpix+(surf->h-1-loopy)*srcpitch)) + surf->w*3 - 3;
          for(loopx = 0; loopx < surf->w; ++loopx)
          {
            dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2];
            dst += 3;
            src -= 3;
          }
        }break;
      }
    }
    else
    {
      switch(surf->format->BytesPerPixel)
      {
      case 1:
        for(loopy = 0; loopy < surf->h; ++loopy) {
          Uint8* dst = (Uint8*)(dstpix+loopy*dstpitch);
          Uint8* src = ((Uint8*)(srcpix+loopy*srcpitch)) + surf->w - 1;
          for(loopx = 0; loopx < surf->w; ++loopx)
            *dst++ = *src--;
        }break;
      case 2:
        for(loopy = 0; loopy < surf->h; ++loopy) {
          Uint16* dst = (Uint16*)(dstpix+loopy*dstpitch);
          Uint16* src = ((Uint16*)(srcpix+loopy*srcpitch)) + surf->w - 1;
          for(loopx = 0; loopx < surf->w; ++loopx)
            *dst++ = *src--;
        }break;
      case 4:
        for(loopy = 0; loopy < surf->h; ++loopy) {
          Uint32* dst = (Uint32*)(dstpix+loopy*dstpitch);
          Uint32* src = ((Uint32*)(srcpix+loopy*srcpitch)) + surf->w - 1;
          for(loopx = 0; loopx < surf->w; ++loopx)
            *dst++ = *src--;
        }break;
      case 3:
        for(loopy = 0; loopy < surf->h; ++loopy) {
          Uint8* dst = (Uint8*)(dstpix+loopy*dstpitch);
          Uint8* src = ((Uint8*)(srcpix+loopy*srcpitch)) + surf->w*3 - 3;
          for(loopx = 0; loopx < surf->w; ++loopx)
          {
            dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2];
            dst += 3;
            src -= 3;
          }
        }break;
      }
    }
  }

  SDL_UnlockSurface(newsurf);
  /* Thanks, Pygame :) */


  if(newsurf == NULL)
    rb_raise(eSDLError,"Could not flip surface: %s",SDL_GetError());
  return Data_Wrap_Struct(cSurface,0,SDL_FreeSurface,newsurf);
}

Return the color [r,g,b,a] of the pixel at the given coordinate.

Raises IndexError if the coordinates are out of bounds.

[Source]

/* 
 *  call-seq: 
 *     get_at(x,y)
 *     get_at([x,y]) # deprecated
 *
 *  Return the color [r,g,b,a] of the pixel at the given coordinate. 
 *
 *  Raises IndexError if the coordinates are out of bounds.
 */
VALUE rbgm_surface_getat( int argc, VALUE *argv, VALUE self )
{
        SDL_Surface *surf;
        int x, y, locked;
        Uint32 color;
        Uint8 *pixels, *pix;
        Uint8 r,g,b,a;
        VALUE vx, vy;

        Data_Get_Struct(self, SDL_Surface, surf);

        rb_scan_args(argc, argv, "11", &vx, &vy);

        /* Still support passing position as an Array... for now. */
        switch( TYPE(vx) )
        {
                case T_ARRAY: {
                        x = NUM2INT( rb_ary_entry(vx,0) );
                        y = NUM2INT( rb_ary_entry(vx,1) );
                        break;
                }
                default: {
                        x = NUM2INT(vx);
                        y = NUM2INT(vy);
                        break;
                }
        }

        if( x < 0 || x > surf->w )
                rb_raise(rb_eIndexError,"x index out of bounds (%d, min 0, max %d)",\
                        x,surf->w);
        if( y < 0 || y > surf->h )
                rb_raise(rb_eIndexError,"y index out of bounds (%d, min 0, max %d)",\
                        y,surf->h);

        locked = 0;
        /* lock surface */
        if(SDL_MUSTLOCK(surf))
        {
                if(SDL_LockSurface(surf)==0)
                        locked += 1;
                else
                        rb_raise(eSDLError,"could not lock surface: %s",SDL_GetError());
        }

/* borrowed from pygame */
        pixels = (Uint8 *) surf->pixels;

        switch(surf->format->BytesPerPixel)
        {
                case 1:
                        color = (Uint32)*((Uint8 *)(pixels + y * surf->pitch) + x);
                        break;
                case 2:
                        color = (Uint32)*((Uint16 *)(pixels + y * surf->pitch) + x);
                        break;
                case 3:
                        pix = ((Uint8 *)(pixels + y * surf->pitch) + x * 3);
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
                        color = (pix[0]) + (pix[1]<<8) + (pix[2]<<16);
#else
                        color = (pix[2]) + (pix[1]<<8) + (pix[0]<<16);
#endif
                        break;
                default: /*case 4:*/
                        color = *((Uint32*)(pixels + y * surf->pitch) + x);
                        break;
        }

/* end borrowed from pygame */

        /* recursively unlock surface*/
        while(locked>1)
        {
                SDL_UnlockSurface(surf);
                locked -= 1;
        }

        SDL_GetRGBA(color, surf->format, &r, &g, &b, &a);
        return rb_ary_new3(4,UINT2NUM(r),UINT2NUM(g),UINT2NUM(b),UINT2NUM(a));
}

Return the height (in pixels) of the surface.

[Source]

/* 
 *  call-seq:
 *     height
 *     h
 *
 *  Return the height (in pixels) of the surface. 
 */
VALUE rbgm_surface_get_h(VALUE self)
{
        SDL_Surface *surf;
        Data_Get_Struct(self, SDL_Surface, surf);
        return INT2NUM(surf->h);
}
height()

Alias for h

Return a Rect with the same width and height as the Surface, positioned at (0,0).

[Source]

# File lib/rubygame/rect.rb, line 607
        def make_rect()
                return Rect.new(0,0,self.width,self.height)
        end

Return the color masks [r,g,b,a] of the surface. Almost everyone can ignore this function. Color masks are used to separate an integer representation of a color into its seperate channels.

[Source]

/* 
 *  call-seq:
 *    masks  ->  [r,g,b,a]
 *
 *  Return the color masks [r,g,b,a] of the surface. Almost everyone can
 *  ignore this function. Color masks are used to separate an
 *  integer representation of a color into its seperate channels.
 */
VALUE rbgm_surface_get_masks(VALUE self)
{
        SDL_Surface *surf;
        SDL_PixelFormat *format;

        Data_Get_Struct(self, SDL_Surface, surf);
        format = surf->format;
        return rb_ary_new3(4,\
                UINT2NUM(format->Rmask),\
                UINT2NUM(format->Gmask),\
                UINT2NUM(format->Bmask),\
                UINT2NUM(format->Amask));
}

Return a string of pixel data for the Surface. Most users will not need to use this method. If you want to convert a Surface into an OpenGL texture, pass the returned string to the TexImage2D method of the ruby-opengl library. (See samples/demo_gl_tex.rb for an example.)

(Please note that the dimensions of OpenGL textures must be powers of 2 (e.g. 64x128, 512x512), so if you want to use a Surface as an OpenGL texture, the Surface‘s dimensions must also be powers of 2!)

[Source]

/*
 *  call-seq:
 *    pixels  ->  String
 *
 *  Return a string of pixel data for the Surface. Most users will not
 *  need to use this method. If you want to convert a Surface into an
 *  OpenGL texture, pass the returned string to the TexImage2D method
 *  of the ruby-opengl library. (See samples/demo_gl_tex.rb for an example.)
 *
 *  (Please note that the dimensions of OpenGL textures must be powers of 2
 *  (e.g. 64x128, 512x512), so if you want to use a Surface as an OpenGL
 *  texture, the Surface's dimensions must also be powers of 2!)
 */
VALUE rbgm_surface_pixels( VALUE self )
{
        SDL_Surface *surf;
        Data_Get_Struct(self, SDL_Surface, surf);
        return rb_str_new(surf->pixels, (long)surf->pitch * surf->h);
}

Return a rotated and/or zoomed version of the given surface. Note that rotating a Surface anything other than a multiple of 90 degrees will cause the new surface to be larger than the original to accomodate the corners (which would otherwise extend beyond the surface).

If Rubygame was compiled with SDL_gfx-2.0.13 or greater, zoom can be an Array of 2 Numerics for separate X and Y scaling. Also, it can be negative to indicate flipping horizontally or vertically.

Will raise SDLError if you attempt to use separate X and Y zoom factors or negative zoom factors with an unsupported version of SDL_gfx.

This method takes these arguments:

angle:degrees to rotate counter-clockwise (negative for clockwise).
zoom:scaling factor(s). A single positive Numeric, unless you have SDL_gfx-2.0.13 or greater (see above).
smooth:whether to anti-alias the new surface. By the way, if true, the new surface will be 32bit RGBA.

[Source]

/*
 *  call-seq:
 *    rotozoom( angle, zoom, smooth=false )  ->  Surface
 *
 *  Return a rotated and/or zoomed version of the given surface. Note that
 *  rotating a Surface anything other than a multiple of 90 degrees will 
 *  cause the new surface to be larger than the original to accomodate the
 *  corners (which would otherwise extend beyond the surface).
 *
 *  If Rubygame was compiled with SDL_gfx-2.0.13 or greater, +zoom+ can be
 *  an Array of 2 Numerics for separate X and Y scaling. Also, it can be
 *  negative to indicate flipping horizontally or vertically.
 *
 *  Will raise SDLError if you attempt to use separate X and Y zoom factors
 *  or negative zoom factors with an unsupported version of SDL_gfx.
 *
 *  This method takes these arguments:
 *  angle::   degrees to rotate counter-clockwise (negative for clockwise).
 *  zoom::    scaling factor(s). A single positive Numeric, unless you have
 *            SDL_gfx-2.0.13 or greater (see above).
 *  smooth::  whether to anti-alias the new surface.
 *            By the way, if true, the new surface will be 32bit RGBA.
 */
VALUE rbgm_transform_rotozoom(int argc, VALUE *argv, VALUE self)
{
  SDL_Surface *src, *dst;
  double angle, zoomx, zoomy;
  int smooth = 0;

  VALUE vangle, vzoom, vsmooth;

  rb_scan_args(argc, argv, "21", &vangle, &vzoom, &vsmooth);

  Data_Get_Struct(self,SDL_Surface,src);

  angle = NUM2DBL(vangle);
  smooth = RTEST(vsmooth) ? 1 : 0;

  switch( TYPE(vzoom) )
  {
   case T_ARRAY: {
     /* separate X and Y factors */
#ifdef HAVE_ROTOZOOMXY
     /* Do the real function. */
     zoomx = NUM2DBL(rb_ary_entry(vzoom,0));
     zoomy = NUM2DBL(rb_ary_entry(vzoom,1));
     dst = rotozoomSurfaceXY(src, angle, zoomx, zoomy, smooth);
     if(dst == NULL)
       rb_raise(eSDLError,"Could not rotozoom surface: %s",SDL_GetError());
#else
     /* Raise SDLError. You should have checked first! */
     rb_raise(eSDLError,"Separate X/Y rotozoom scale factors is not supported by your version of SDL_gfx (%d,%d,%d). Please upgrade to 2.0.13 or later.", SDL_GFXPRIMITIVES_MAJOR, SDL_GFXPRIMITIVES_MINOR, SDL_GFXPRIMITIVES_MICRO);
     return Qnil;
#endif
     break;
   }

    case T_FLOAT:
    case T_FIXNUM: {
      /* uniform factor for both X and Y */
      zoomx = NUM2DBL(vzoom);
#ifndef HAVE_ROTOZOOMXY
      if(zoomx < 0)                /* negative zoom (for flipping) */
      {
        /* Raise SDLError. You should have checked first! */
        rb_raise(eSDLError,"Negative rotozoom scale factor is not supported by your version of SDL_gfx (%d,%d,%d). Please upgrade to 2.0.13 or later.", SDL_GFXPRIMITIVES_MAJOR, SDL_GFXPRIMITIVES_MINOR, SDL_GFXPRIMITIVES_MICRO);
      }
#endif
      dst = rotozoomSurface(src, angle, zoomx, smooth);
      if(dst == NULL)
        rb_raise(eSDLError,"Could not rotozoom surface: %s",SDL_GetError());
      break;
    }

    default: {
      rb_raise(rb_eArgError,
               "wrong zoom factor type (expected Array or Numeric)");
      break;
    }

  }

  return Data_Wrap_Struct(cSurface,0,SDL_FreeSurface,dst);
}

Save the Surface as a Windows Bitmap (BMP) file with the given filename.

[Source]

/* 
 *  call-seq:
 *    savebmp( filename )  ->  nil
 *
 *  Save the Surface as a Windows Bitmap (BMP) file with the given filename.
 */
VALUE rbgm_image_savebmp( VALUE self, VALUE filename )
{
        char *name;
        SDL_Surface *surf;

        name = StringValuePtr(filename);
        Data_Get_Struct(self,SDL_Surface,surf);
        if(SDL_SaveBMP(surf,name)!=0)
        {
                rb_raise(eSDLError,\
                        "Couldn't save surface to file %s: %s",name,SDL_GetError());
        }
        return Qnil;
}

Set the per-surface alpha (opacity; non-transparency) of the surface.

This function takes these arguments:

alpha:requested opacity of the surface. Alpha must be from 0 (fully transparent) to 255 (fully opaque).
flags:0 or Rubygame::SRC_ALPHA (default). Most people will want the default, in which case this argument can be omitted. For advanced users: this flag affects the surface as described in the docs for the SDL C function, SDL_SetAlpha.

[Source]

/*
 *  call-seq:
 *     set_alpha(alpha, flags=Rubygame::SRC_ALPHA)
 *
 *  Set the per-surface alpha (opacity; non-transparency) of the surface.
 *
 *  This function takes these arguments:
 *  alpha:: requested opacity of the surface. Alpha must be from 0 
 *          (fully transparent) to 255 (fully opaque).
 *  flags:: 0 or Rubygame::SRC_ALPHA (default). Most people will want the
 *          default, in which case this argument can be omitted. For advanced
 *          users: this flag affects the surface as described in the docs for
 *          the SDL C function, SDL_SetAlpha.
 */
VALUE rbgm_surface_set_alpha(int argc, VALUE *argv, VALUE self)
{
        SDL_Surface *surf;
        Uint8 alpha;
        Uint32 flags = SDL_SRCALPHA;
        VALUE valpha, vflags;

        rb_scan_args(argc, argv, "11", &valpha, &vflags);

        if( !NIL_P(vflags) )
        {
                flags = NUM2UINT(vflags);
        }

        alpha = NUM2UINT(valpha);

        Data_Get_Struct(self, SDL_Surface, surf);
        if( SDL_SetAlpha(surf,flags,alpha) != 0 )
                rb_raise(eSDLError, "%s", SDL_GetError());
        return self;
}

Set the color of the pixel at the given coordinate.

color can be one of:

  • an Array, [r,g,b] or [r,g,b,a] with each component in 0-255
  • an instance of ColorRGB, ColorHSV, etc.
  • the name of a color in Rubygame::Color, as a Symbol or String

Raises IndexError if the coordinates are out of bounds.

[Source]

/* 
 *  call-seq:
 *     set_at([x,y], color)
 *
 *  Set the color of the pixel at the given coordinate.
 *
 *  color can be one of:
 *  * an Array, [r,g,b] or [r,g,b,a] with each component in 0-255
 *  * an instance of ColorRGB, ColorHSV, etc.
 *  * the name of a color in Rubygame::Color, as a Symbol or String
 *
 *  Raises IndexError if the coordinates are out of bounds.
 *
 *--
 *
 *  I'm lazy and just using SDL_FillRect. ;-P
 *  It's easier and less bug-prone this way.
 *  I have no idea about speed comparisons.
 *
 */
VALUE rbgm_surface_setat( int argc, VALUE *argv, VALUE self )
{
        SDL_Surface *surf;
        SDL_Rect *rect;
        Uint32 color;
        Uint8 r,g,b,a;
        VALUE vpos, vcolor;

        Data_Get_Struct(self, SDL_Surface, surf);

        rb_scan_args(argc, argv, "2", &vpos, &vcolor);

        vcolor = convert_color(vcolor);
        extract_rgba_u8_as_u8(vcolor, &r, &g, &b, &a);
        color = SDL_MapRGBA(surf->format, r,g,b,a);

        vpos = convert_to_array(vpos);
        rect = make_rect( NUM2INT(rb_ary_entry(vpos,0)),
                          NUM2INT(rb_ary_entry(vpos,1)),
                          1, 1 );

        SDL_FillRect(surf,rect,color);

        free(rect);

        return self;
}

Set the colorkey of the surface. See Surface#colorkey for a description of colorkeys.

This method takes these arguments:

color:color to use as the key, in the form [r,g,b]. Can be nil to un-set the colorkey.
flags:0 or Rubygame::SRC_COLORKEY (default) or Rubygame::SRC_COLORKEY|Rubygame::SDL_RLEACCEL. Most people will want the default, in which case this argument can be omitted. For advanced users: this flag affects the surface as described in the docs for the SDL C function, SDL_SetColorkey.

[Source]

/*
 *  call-seq:
 *     set_colorkey(color,flags=0)
 *
 *  Set the colorkey of the surface. See Surface#colorkey for a description
 *  of colorkeys.
 *
 *  This method takes these arguments:
 *  color:: color to use as the key, in the form [r,g,b]. Can be +nil+ to
 *          un-set the colorkey.
 *  flags:: 0 or Rubygame::SRC_COLORKEY (default) or 
 *          Rubygame::SRC_COLORKEY|Rubygame::SDL_RLEACCEL. Most people will 
 *          want the default, in which case this argument can be omitted. For
 *          advanced users: this flag affects the surface as described in the
 *          docs for the SDL C function, SDL_SetColorkey.
 */
VALUE rbgm_surface_set_colorkey( int argc, VALUE *argv, VALUE self)
{
        SDL_Surface *surf;
        Uint32 color;
        Uint32 flags;
        Uint8 r,g,b;
        VALUE vcolor, vflags;

        Data_Get_Struct(self, SDL_Surface, surf);

        rb_scan_args(argc, argv, "11", &vcolor, &vflags);

        if( !NIL_P(vflags) )
        {
                flags = NUM2UINT(vflags);
        }
        else
        {
                flags = SDL_SRCCOLORKEY;
        }


        if( RTEST(vcolor) )
        {
                vcolor = convert_color(vcolor);
                extract_rgb_u8_as_u8(vcolor, &r, &g, &b);
                color = SDL_MapRGB(surf->format, r,g,b);
        }
        else
        {
                flags = 0;
                color = 0;
        }

        if(SDL_SetColorKey(surf,flags,color)!=0)
                rb_raise(eSDLError,"could not set colorkey: %s",SDL_GetError());
        return self;
}

Return the surface‘s width and height (in pixels) in an Array.

[Source]

/*  call-seq:
 *    size  ->  [w,h]
 *
 *  Return the surface's width and height (in pixels) in an Array.
 */
VALUE rbgm_surface_get_size(VALUE self)
{
        SDL_Surface *surf;
        Data_Get_Struct(self, SDL_Surface, surf);
        return rb_ary_new3( 2, INT2NUM(surf->w), INT2NUM(surf->h) );
}

Copies the Surface to a new Surface with the pixel format of the display, suitable for fast blitting to the display surface (i.e. Screen). May raise SDLError if a problem occurs.

If you want to take advantage of hardware colorkey or alpha blit acceleration, you should set the colorkey and alpha value before calling this function.

[Source]

/* 
 *  call-seq: 
 *    to_display()  ->  Surface
 *
 *  Copies the Surface to a new Surface with the pixel format of the display,
 *  suitable for fast blitting to the display surface (i.e. Screen).
 *  May raise SDLError if a problem occurs.
 *
 *  If you want to take advantage of hardware colorkey or alpha blit
 *  acceleration, you should set the colorkey and alpha value before calling
 *  this function. 
 *
 */
VALUE rbgm_surface_dispform(VALUE self)
{
        SDL_Surface *surf, *newsurf;
        Data_Get_Struct(self, SDL_Surface, surf);

  if( init_video_system() == 0 )
  {
    newsurf = SDL_DisplayFormat( surf );
  }
  else
  {
    newsurf = NULL;
  }

  if( newsurf == NULL )
  {
    rb_raise(eSDLError,\
             "Could not convert the Surface to display format: %s",\
             SDL_GetError());
  }

  return Data_Wrap_Struct( cSurface,0,SDL_FreeSurface,newsurf );  
}

Like to_display except the Surface has an extra channel for alpha (i.e. opacity). May raise SDLError if a problem occurs.

This function can be used to convert a colorkey to an alpha channel, if the SRCCOLORKEY flag is set on the surface. The generated surface will then be transparent (alpha=0) where the pixels match the colorkey, and opaque (alpha=255) elsewhere.

[Source]

/* 
 *  call-seq: 
 *    to_display_alpha()  ->  Surface
 *
 *  Like #to_display except the Surface has an extra channel for alpha (i.e.
 *  opacity). May raise SDLError if a problem occurs.
 *
 *  This function can be used to convert a colorkey to an alpha channel, if the
 *  SRCCOLORKEY flag is set on the surface. The generated surface will then be
 *  transparent (alpha=0) where the pixels match the colorkey, and opaque
 *  (alpha=255) elsewhere. 
 */
VALUE rbgm_surface_dispformalpha(VALUE self)
{
        SDL_Surface *surf, *newsurf;
        Data_Get_Struct(self, SDL_Surface, surf);

  if( init_video_system() == 0 )
  {
    newsurf = SDL_DisplayFormatAlpha( surf );
  }
  else
  {
    newsurf = NULL;
  }

  if( newsurf == NULL )
  {
    rb_raise(eSDLError,\
             "Could not convert the Surface to display format with alpha channel: %s",\
             SDL_GetError());
  }

  return Data_Wrap_Struct( cSurface,0,SDL_FreeSurface,newsurf );  
}

Return the width (in pixels) of the surface.

[Source]

/* 
 *  call-seq:
 *     width
 *     w
 *
 *  Return the width (in pixels) of the surface. 
 */
VALUE rbgm_surface_get_w(VALUE self)
{
        SDL_Surface *surf;
        Data_Get_Struct(self, SDL_Surface, surf);
        return INT2NUM(surf->w);
}
width()

Alias for w

Return a zoomed version of the Surface.

This method takes these arguments:

zoom:a Numeric factor to scale by in both x and y directions, or an Array with separate x and y scale factors.
smooth:whether to anti-alias the new surface. By the way, if true, the new surface will be 32bit RGBA.

[Source]

/* 
 *  call-seq:
 *     zoom(zoom, smooth=false)  ->  Surface
 *
 *  Return a zoomed version of the Surface.
 *
 *  This method takes these arguments:
 *  zoom::    a Numeric factor to scale by in both x and y directions,
 *            or an Array with separate x and y scale factors.
 *  smooth::  whether to anti-alias the new surface.
 *            By the way, if true, the new surface will be 32bit RGBA.
 */
VALUE rbgm_transform_zoom(int argc, VALUE *argv, VALUE self)
{
  SDL_Surface *src, *dst;
  double zoomx, zoomy;
  int smooth = 0;

  VALUE vzoom, vsmooth;

  rb_scan_args(argc, argv, "11", &vzoom, &vsmooth);

  Data_Get_Struct(self,SDL_Surface,src);

  smooth = RTEST(vsmooth) ? 1 : 0;

  switch( TYPE(vzoom) )
  {
    case T_ARRAY:{
      zoomx = NUM2DBL(rb_ary_entry(vzoom,0));
      zoomy = NUM2DBL(rb_ary_entry(vzoom,1));
      break;
    }
    case T_FLOAT:
    case T_FIXNUM: {
      zoomx = NUM2DBL(argv[0]);
      zoomy = zoomx;
      break;
    }
    default: {
      rb_raise(rb_eArgError,
               "wrong zoom factor type (expected Array or Numeric)");
      break;
    }

  }
  dst = zoomSurface(src,zoomx,zoomy,smooth);
  if(dst == NULL)
    rb_raise(eSDLError,"Could not rotozoom surface: %s",SDL_GetError());
  return Data_Wrap_Struct(cSurface,0,SDL_FreeSurface,dst);
}

Return a zoomed version of the Surface.

This method takes these arguments:

width:the width to scale to. If nil is given, will keep x axis unscaled.
height:the height to scale to. If nil is given, will keep x axis unscaled.
smooth:whether to anti-alias the new surface. This option can be omitted, in which case the surface will not be anti-aliased. If true, the new surface will be 32bit RGBA.

[Source]

/* 
 *  call-seq:
 *     zoom_to(width, height, smooth=false)  ->  Surface
 *
 *  Return a zoomed version of the Surface.
 *
 *  This method takes these arguments:
 *  width::   the width to scale to. If nil is given, will keep x axis unscaled.
 *  height::  the height to scale to. If nil is given, will keep x axis
 *            unscaled.
 *  smooth::  whether to anti-alias the new surface. This option can be
 *            omitted, in which case the surface will not be anti-aliased.
 *            If true, the new surface will be 32bit RGBA.
 */
VALUE rbgm_transform_zoom_to(int argc, VALUE *argv, VALUE self)
{
  SDL_Surface *src, *dst;
  VALUE v_width, v_height, v_smooth;
  double zoomx, zoomy;
  int smooth;

  rb_scan_args(argc, argv, "21", &v_width, &v_height, &v_smooth);

  Data_Get_Struct(self,SDL_Surface,src);
  smooth = RTEST(v_smooth) ? 1 : 0;
  zoomx  = NIL_P(v_width) ? 1.0 : NUM2DBL(v_width)/src->w;
  zoomy  = NIL_P(v_height) ? 1.0 : NUM2DBL(v_height)/src->h;
  dst    = zoomSurface(src,zoomx,zoomy,smooth);

  if(dst == NULL)
    rb_raise(eSDLError,"Could not rotozoom surface: %s",SDL_GetError());

  return Data_Wrap_Struct(cSurface,0,SDL_FreeSurface,dst);
}

[Validate]