/* RUDL - a C library wrapping SDL for use in Ruby. Copyright (C) 2001, 2002, 2003 Danny van Bruggen $Log: rudl_video_sdl_gfx.c,v $ Revision 1.15 2004/10/23 19:54:22 rennex Fixed docs Revision 1.14 2004/08/04 23:03:46 tsuihark Updated all documentation to Dokumentat format. Revision 1.13 2004/01/21 22:55:10 tsuihark Converted to Dokumentat format. Revision 1.12 2003/12/26 22:40:44 rennex Combined Surface#plot and Surface#[]= into one method Revision 1.11 2003/09/26 22:43:16 tsuihark Added CVS headers */ #include "rudl_events.h" #include "rudl_video.h" #ifdef HAVE_SDL_ROTOZOOM_H #include "SDL_rotozoom.h" #endif #ifdef HAVE_SDL_GFXPRIMITIVES_H #include "SDL_gfxPrimitives.h" #endif ///////////////////////////////// SDL_GFX: ROTOZOOM #ifdef HAVE_SDL_ROTOZOOM_H /** @file Surface @class Surface @section Drawing Many of the methods here are from SDL_gfx. They were written by Andreas Schiffler. */ /** @section Scaling, Flipping and Rotating @method rotozoom( angle, zoom, smooth ) => Surface Returns a new surface that is rotated @angle degrees and zoomed @zoom times (fractions are OK). This method returns a 32 bit surface. Exception: for now it returns an 8 bit surface when fed an 8 bit surface. If @smooth is true and the surface is not 8 bits, bilinear interpolation will be applied, resulting in a smoother image. */ static VALUE surface_rotozoom(VALUE self, VALUE angle, VALUE zoom, VALUE smooth) { return createSurfaceObject(rotozoomSurface(retrieveSurfacePointer(self), NUM2DBL(angle), NUM2DBL(zoom), NUM2BOOL(smooth))); } /** @method zoom( zoom_horizontal, zoom_vertical, smooth ) => Surface Returns a new surface that is zoomed. 1.0 doesn't zoom, bigger than 1.0 zooms in, smaller than 1.0 zooms out. This method returns a 32 bit surface. Exception: for now it returns an 8 bit surface when fed an 8 bit surface. If @smooth is true and the surface is not 8 bits, bilinear interpolation will be applied, resulting in a smoother image. (The last two methods are from Andreas Schiffler's SDL_rotozoom, aschiffler@home.com) */ static VALUE surface_zoom(VALUE self, VALUE zoom_x, VALUE zoom_y, VALUE smooth) { return createSurfaceObject(zoomSurface(retrieveSurfacePointer(self), NUM2DBL(zoom_x), NUM2DBL(zoom_y), NUM2BOOL(smooth))); } #endif ///////////////////////////////// SDL_GFX: GFXPRIMITIVES #ifdef HAVE_SDL_GFXPRIMITIVES_H /** @section Drawing For these methods, "antialiased" means that drawing is done with many shades of the requested color to simulate */ /** @method plot( x, y, color ) -> self @method plot( coordinate, color ) -> self @method [ x, y ]= color -> self @method [ coordinate ]= color -> self These methods access single pixels on a surface. @plot or @[]= set the color of a pixel. The coordinate can be given as an [x,y] array or two separate numbers. @plot is an alias for @[]=. These methods require the surface to be locked if necessary. @[]= and @[] are the only methods in RUDL that take separate x and y coordinates. See also: @Surface.get, @Surface.[] */ static VALUE surface_plot(int argc, VALUE* argv, VALUE self) { Sint16 x,y; Uint32 color; /* did we get a coordinate array? */ if (argc == 2) { PARAMETER2COORD(argv[0], &x, &y); color = VALUE2COLOR_NOMAP(argv[1]); } else if (argc == 3) { /* what about separate coordinates? */ x = NUM2Sint16(argv[0]); y = NUM2Sint16(argv[1]); color = VALUE2COLOR_NOMAP(argv[2]); } else { /* no, something else */ rb_raise(rb_eArgError, "wrong number of arguments"); } if(pixelColor(retrieveSurfacePointer(self), x, y, color)) SDL_RAISE_S("failed"); return self; } /* static VALUE surface_array_plot(VALUE self, VALUE x, VALUE y, VALUE color) { if(pixelColor(retrieveSurfacePointer(self), NUM2Sint16(x), NUM2Sint16(y), VALUE2COLOR_NOMAP(color))) SDL_RAISE_S("failed"); return self; } */ /** @section Drawing: Straight stuff @method horizontal_line( coord, endx, color ) => self */ static VALUE surface_horizontal_line(VALUE self, VALUE coord, VALUE endx, VALUE color) { Sint16 x,y; PARAMETER2COORD(coord, &x, &y); if(hlineColor(retrieveSurfacePointer(self), x, NUM2Sint16(endx), y, VALUE2COLOR_NOMAP(color))) SDL_RAISE_S("failed"); return self; } /** @method vertical_line( coord, endy, color ) => self */ static VALUE surface_vertical_line(VALUE self, VALUE coord, VALUE endy, VALUE color) { Sint16 x,y; PARAMETER2COORD(coord, &x, &y); if(vlineColor(retrieveSurfacePointer(self), x, y, NUM2Sint16(endy), VALUE2COLOR_NOMAP(color))) SDL_RAISE_S("failed"); return self; } /** @method rectangle( rect, color ) => self */ static VALUE surface_rectangle(VALUE self, VALUE rectObject, VALUE color) { SDL_Rect rect; PARAMETER2CRECT(rectObject, &rect); if(rectangleColor(retrieveSurfacePointer(self), rect.x, rect.y, (Sint16)(rect.x+rect.w-1), (Sint16)(rect.y+rect.h-1), VALUE2COLOR_NOMAP(color))) SDL_RAISE_S("failed"); return self; } /** @method filled_rectangle( rect, color ) => self Filled_rectangle is a lot like @fill. Fill comes from SDL, filled_rectangle from SDL_gfx, choose whichever you like best. */ static VALUE surface_filled_rectangle(VALUE self, VALUE rectObject, VALUE color) { SDL_Rect rect; PARAMETER2CRECT(rectObject, &rect); if(boxColor(retrieveSurfacePointer(self), rect.x, rect.y, (Sint16)(rect.x+rect.w-1), (Sint16)(rect.y+rect.h-1), VALUE2COLOR_NOMAP(color))) SDL_RAISE_S("failed"); return self; } /** @method line( coord1, coord2, color ) */ static VALUE surface_line(VALUE self, VALUE coord1, VALUE coord2, VALUE color) { Sint16 x1,y1,x2,y2; PARAMETER2COORD(coord1, &x1, &y1); PARAMETER2COORD(coord2, &x2, &y2); if(lineColor(retrieveSurfacePointer(self), x1, y1, x2, y2, VALUE2COLOR_NOMAP(color))) SDL_RAISE_S("failed"); return self; } /** @method antialiased_line( coord1, coord2, color ) -> self*/ static VALUE surface_antialiased_line(VALUE self, VALUE coord1, VALUE coord2, VALUE color) { Sint16 x1,y1,x2,y2; PARAMETER2COORD(coord1, &x1, &y1); PARAMETER2COORD(coord2, &x2, &y2); if(aalineColor(retrieveSurfacePointer(self), x1, y1, x2, y2, VALUE2COLOR_NOMAP(color))) SDL_RAISE_S("failed"); return self; } /** @section Drawing: Circles @method circle( coord, radius, color ) -> self */ static VALUE surface_circle(VALUE self, VALUE coord, VALUE r, VALUE color) { Sint16 x,y; PARAMETER2COORD(coord, &x, &y); if(circleColor(retrieveSurfacePointer(self), x, y, NUM2Sint16(r), VALUE2COLOR_NOMAP(color))) SDL_RAISE_S("failed"); return self; } /** @method filled_circle( coord, radius, color ) -> self*/ static VALUE surface_filled_circle(VALUE self, VALUE coord, VALUE r, VALUE color) { Sint16 x,y; PARAMETER2COORD(coord, &x, &y); if(filledCircleColor(retrieveSurfacePointer(self), x, y, NUM2Sint16(r), VALUE2COLOR_NOMAP(color))) SDL_RAISE_S("failed"); return self; } /** @method antialiased_circle( coord, radius, color ) -> self*/ static VALUE surface_antialiased_circle(VALUE self, VALUE coord, VALUE r, VALUE color) { Sint16 x,y; PARAMETER2COORD(coord, &x, &y); if(aacircleColor(retrieveSurfacePointer(self), x, y, NUM2Sint16(r), VALUE2COLOR_NOMAP(color))) SDL_RAISE_S("failed"); return self; } /** @method filled_pie( coord, radius, start, end, color ) -> self*/ static VALUE surface_filled_pie(VALUE self, VALUE coord, VALUE r, VALUE start, VALUE end, VALUE color) { Sint16 x,y; PARAMETER2COORD(coord, &x, &y); if(filledpieColor(retrieveSurfacePointer(self), x, y, NUM2Sint16(r), NUM2Sint16(start), NUM2Sint16(end), VALUE2COLOR_NOMAP(color))) SDL_RAISE_S("failed"); return self; } /** @method ellipse( coord, radius_x, radius_y, color ) -> self*/ static VALUE surface_ellipse(VALUE self, VALUE coord, VALUE rx, VALUE ry, VALUE color) { Sint16 x,y; PARAMETER2COORD(coord, &x, &y); if(ellipseColor(retrieveSurfacePointer(self), x, y, NUM2Sint16(rx), NUM2Sint16(ry), VALUE2COLOR_NOMAP(color))) SDL_RAISE_S("failed"); return self; } /** @method antialiased_ellipse( coord, radius_x, radius_y, color ) -> self*/ static VALUE surface_antialiased_ellipse(VALUE self, VALUE coord, VALUE rx, VALUE ry, VALUE color) { Sint16 x,y; PARAMETER2COORD(coord, &x, &y); if(aaellipseColor(retrieveSurfacePointer(self), x, y, NUM2Sint16(rx), NUM2Sint16(ry), VALUE2COLOR_NOMAP(color))) SDL_RAISE_S("failed"); return self; } /** @method filled_ellipse( coord, radius_x, radius_y, color ) -> self*/ static VALUE surface_filled_ellipse(VALUE self, VALUE coord, VALUE rx, VALUE ry, VALUE color) { Sint16 x,y; PARAMETER2COORD(coord, &x, &y); if(filledEllipseColor(retrieveSurfacePointer(self), x, y, NUM2Sint16(rx), NUM2Sint16(ry), VALUE2COLOR_NOMAP(color))) SDL_RAISE_S("failed"); return self; } /** @section Drawing: Polygons The polygon methods take an array of [x,y], like [[10,10],[40,60],[16,66]]. */ /** @method polygon( coord_list, color ) -> self */ static VALUE surface_polygon(VALUE self, VALUE coordlist, VALUE color) { int numpoints=RARRAY(coordlist)->len; Sint16 *x=malloc(sizeof(Sint16)*numpoints); Sint16 *y=malloc(sizeof(Sint16)*numpoints); int i; VALUE tmp; for(i=0; i self */ static VALUE surface_filled_polygon(VALUE self, VALUE coordlist, VALUE color) { int numpoints=RARRAY(coordlist)->len; Sint16 *x=malloc(sizeof(Sint16)*numpoints); Sint16 *y=malloc(sizeof(Sint16)*numpoints); int i; VALUE tmp; for(i=0; i self */ static VALUE surface_antialiased_polygon(VALUE self, VALUE coordlist, VALUE color) { int numpoints=RARRAY(coordlist)->len; Sint16 *x=malloc(sizeof(Sint16)*numpoints); Sint16 *y=malloc(sizeof(Sint16)*numpoints); int i; VALUE tmp; for(i=0; i self Puts @text on the surface in a monospaced 8x8 standard old ASCII font. */ static VALUE surface_print(VALUE self, VALUE coord, VALUE text, VALUE color) { Sint16 x,y; PARAMETER2COORD(coord, &x, &y); if(stringColor(retrieveSurfacePointer(self), x, y, STR2CSTR(text), VALUE2COLOR_NOMAP(color))) SDL_RAISE_S("failed"); return self; } #endif #ifdef HAVE_SDL_IMAGEFILTER_H /* Unsupported for now (don't know how they work yet) == SDL_gfx: SDL_imageFilter --- Surface#filterMMXdetect --- Surface#filterEnableMMX( true_or_false ) --- Surface#filterAdd: D = saturation255(S1 + S2) --- Surface#filterMean: D = S1/2 + S2/2 SDL_imageFilterSub: D = saturation0(S1 - S2) SDL_imageFilterAbsDiff: D = | S1 - S2 | SDL_imageFilterMult: D = saturation(S1 * S2) SDL_imageFilterMultNor: D = S1 * S2 (non-MMX) SDL_imageFilterMultDivby2: D = saturation255(S1/2 * S2) SDL_imageFilterMultDivby4: D = saturation255(S1/2 * S2/2) SDL_imageFilterBitAnd: D = S1 & S2 SDL_imageFilterBitOr: D = S1 | S2 SDL_imageFilterDiv: D = S1 / S2 (non-MMX) SDL_imageFilterBitNegation: D = !S SDL_imageFilterAddByte: D = saturation255(S + C) SDL_imageFilterAddByteToHalf: D = saturation255(S/2 + C) SDL_imageFilterSubByte: D = saturation0(S - C) SDL_imageFilterShiftRight: D = saturation0(S >> N) SDL_imageFilterMultByByte: D = saturation255(S * C) SDL_imageFilterShiftRightAndMultByByte: D = saturation255((S >> N) * C) SDL_imageFilterShiftLeftByte: D = (S << N) SDL_imageFilterShiftLeft: D = saturation255(S << N) SDL_imageFilterBinarizeUsingThreshold: D = S >= T ? 255:0 SDL_imageFilterClipToRange: D = (S >= Tmin) & (S <= Tmax) 255:0 SDL_imageFilterNormalizeLinear: D = saturation255((Nmax - Nmin)/(Cmax - Cmin)*(S - Cmin) + Nmin) !!! NO C-ROUTINE FOR THESE FUNCTIONS YET !!! SDL_imageFilterConvolveKernel3x3Divide: Dij = saturation0and255( ... ) SDL_imageFilterConvolveKernel5x5Divide: Dij = saturation0and255( ... ) SDL_imageFilterConvolveKernel7x7Divide: Dij = saturation0and255( ... ) SDL_imageFilterConvolveKernel9x9Divide: Dij = saturation0and255( ... ) SDL_imageFilterConvolveKernel3x3ShiftRight: Dij = saturation0and255( ... ) SDL_imageFilterConvolveKernel5x5ShiftRight: Dij = saturation0and255( ... ) SDL_imageFilterConvolveKernel7x7ShiftRight: Dij = saturation0and255( ... ) SDL_imageFilterConvolveKernel9x9ShiftRight: Dij = saturation0and255( ... ) SDL_imageFilterSobelX: Dij = saturation255( ... ) int SDL_imageFilterAdd (unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, int length); int SDL_imageFilterMean(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, int length); int SDL_imageFilterSub(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, int length); int SDL_imageFilterAbsDiff(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, int length); int SDL_imageFilterMult(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, int length); int SDL_imageFilterMultNor(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, int length); int SDL_imageFilterMultDivby2(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, int length); int SDL_imageFilterMultDivby4(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, int length); int SDL_imageFilterBitAnd(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, int length); int SDL_imageFilterBitOr(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, int length); int SDL_imageFilterDiv(unsigned char *Src1, unsigned char *Src2, unsigned char *Dest, int length); int SDL_imageFilterBitNegation(unsigned char *Src1, unsigned char *Dest, int length); int SDL_imageFilterAddByte(unsigned char *Src1, unsigned char *Dest, int length, unsigned char C); int SDL_imageFilterAddByteToHalf(unsigned char *Src1, unsigned char *Dest, int length, unsigned char C); int SDL_imageFilterSubByte(unsigned char *Src1, unsigned char *Dest, int length, unsigned char C); int SDL_imageFilterShiftRight(unsigned char *Src1, unsigned char *Dest, int length, unsigned char N); int SDL_imageFilterMultByByte(unsigned char *Src1, unsigned char *Dest, int length, unsigned char C); int SDL_imageFilterShiftRightAndMultByByte(unsigned char *Src1, unsigned char *Dest, int length, unsigned char N, unsigned char C); int SDL_imageFilterShiftLeftByte(unsigned char *Src1, unsigned char *Dest, int length, unsigned char N); int SDL_imageFilterShiftLeft(unsigned char *Src1, unsigned char *Dest, int length, unsigned char N); int SDL_imageFilterBinarizeUsingThreshold(unsigned char *Src1, unsigned char *Dest, int length, unsigned char T); int SDL_imageFilterClipToRange(unsigned char *Src1, unsigned char *Dest, int length, unsigned char Tmin, unsigned char Tmax); int SDL_imageFilterNormalizeLinear(unsigned char *Src1, unsigned char *Dest, int length, int Cmin, int Cmax, int Nmin, int Nmax); int SDL_imageFilterConvolveKernel3x3Divide(unsigned char *Src, unsigned char *Dest, int rows, int columns, signed short *Kernel, unsigned char Divisor); int SDL_imageFilterConvolveKernel5x5Divide(unsigned char *Src, unsigned char *Dest, int rows, int columns, signed short *Kernel, unsigned char Divisor); int SDL_imageFilterConvolveKernel7x7Divide(unsigned char *Src, unsigned char *Dest, int rows, int columns, signed short *Kernel, unsigned char Divisor); int SDL_imageFilterConvolveKernel9x9Divide(unsigned char *Src, unsigned char *Dest, int rows, int columns, signed short *Kernel, unsigned char Divisor); int SDL_imageFilterConvolveKernel3x3ShiftRight(unsigned char *Src, unsigned char *Dest, int rows, int columns, signed short *Kernel, unsigned char NRightShift); int SDL_imageFilterConvolveKernel5x5ShiftRight(unsigned char *Src, unsigned char *Dest, int rows, int columns, signed short *Kernel, unsigned char NRightShift); int SDL_imageFilterConvolveKernel7x7ShiftRight(unsigned char *Src, unsigned char *Dest, int rows, int columns, signed short *Kernel, unsigned char NRightShift); int SDL_imageFilterConvolveKernel9x9ShiftRight(unsigned char *Src, unsigned char *Dest, int rows, int columns, signed short *Kernel, unsigned char NRightShift); int SDL_imageFilterSobelX(unsigned char *Src, unsigned char *Dest, int rows, int columns); */ #endif ///////////////////////////////// INIT void initVideoSDLGFXClasses() { //classSurfaceArray=rb_define_class_under(moduleRUDL, "SurfaceArray", rb_cObject); #ifdef HAVE_SDL_GFXPRIMITIVES_H rb_define_method(classSurface, "[]=", surface_plot, -1); rb_alias(classSurface, rb_intern("plot"), rb_intern("[]=")); rb_define_method(classSurface, "horizontal_line", surface_horizontal_line, 3); rb_define_method(classSurface, "vertical_line", surface_vertical_line, 3); rb_define_method(classSurface, "rectangle", surface_rectangle, 2); rb_define_method(classSurface, "filled_rectangle", surface_filled_rectangle, 2); rb_define_method(classSurface, "line", surface_line, 3); rb_define_method(classSurface, "antialiased_line", surface_antialiased_line, 3); rb_define_method(classSurface, "circle", surface_circle, 3); rb_define_method(classSurface, "filled_circle", surface_filled_circle, 3); rb_define_method(classSurface, "antialiased_circle", surface_antialiased_circle, 3); rb_define_method(classSurface, "filled_pie", surface_filled_pie, 5); rb_define_method(classSurface, "ellipse", surface_ellipse, 4); rb_define_method(classSurface, "filled_ellipse", surface_filled_ellipse, 4); rb_define_method(classSurface, "antialiased_ellipse", surface_antialiased_ellipse, 4); rb_define_method(classSurface, "polygon", surface_polygon, 2); rb_define_method(classSurface, "filled_polygon", surface_filled_polygon, 2); rb_define_method(classSurface, "antialiased_polygon", surface_antialiased_polygon, 2); rb_define_method(classSurface, "print", surface_print, 3); #endif #ifdef HAVE_SDL_ROTOZOOM_H rb_define_method(classSurface, "rotozoom", surface_rotozoom, 3); rb_define_method(classSurface, "zoom", surface_zoom, 3); #endif #ifdef HAVE_SDL_IMAGEFILTER_H #endif }