rubygame 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/CREDITS +50 -0
  2. data/Changelog +162 -0
  3. data/LICENSE +504 -0
  4. data/README +122 -0
  5. data/Rakefile +380 -0
  6. data/TODO +45 -0
  7. data/doc/extended_readme.rdoc +49 -0
  8. data/doc/getting_started.rdoc +47 -0
  9. data/doc/macosx_install.rdoc +74 -0
  10. data/doc/windows_install.rdoc +124 -0
  11. data/ext/rubygame/MANIFEST +25 -0
  12. data/ext/rubygame/rubygame_event.c +644 -0
  13. data/ext/rubygame/rubygame_event.h +48 -0
  14. data/ext/rubygame/rubygame_gfx.c +951 -0
  15. data/ext/rubygame/rubygame_gfx.h +102 -0
  16. data/ext/rubygame/rubygame_gl.c +154 -0
  17. data/ext/rubygame/rubygame_gl.h +32 -0
  18. data/ext/rubygame/rubygame_image.c +108 -0
  19. data/ext/rubygame/rubygame_image.h +41 -0
  20. data/ext/rubygame/rubygame_joystick.c +247 -0
  21. data/ext/rubygame/rubygame_joystick.h +41 -0
  22. data/ext/rubygame/rubygame_main.c +155 -0
  23. data/ext/rubygame/rubygame_main.h +33 -0
  24. data/ext/rubygame/rubygame_mixer.c +764 -0
  25. data/ext/rubygame/rubygame_mixer.h +62 -0
  26. data/ext/rubygame/rubygame_screen.c +420 -0
  27. data/ext/rubygame/rubygame_screen.h +41 -0
  28. data/ext/rubygame/rubygame_shared.c +152 -0
  29. data/ext/rubygame/rubygame_shared.h +54 -0
  30. data/ext/rubygame/rubygame_surface.c +1107 -0
  31. data/ext/rubygame/rubygame_surface.h +62 -0
  32. data/ext/rubygame/rubygame_time.c +183 -0
  33. data/ext/rubygame/rubygame_time.h +32 -0
  34. data/ext/rubygame/rubygame_ttf.c +600 -0
  35. data/ext/rubygame/rubygame_ttf.h +69 -0
  36. data/lib/rubygame.rb +40 -0
  37. data/lib/rubygame/MANIFEST +12 -0
  38. data/lib/rubygame/clock.rb +128 -0
  39. data/lib/rubygame/constants.rb +238 -0
  40. data/lib/rubygame/event.rb +313 -0
  41. data/lib/rubygame/ftor.rb +370 -0
  42. data/lib/rubygame/hotspot.rb +265 -0
  43. data/lib/rubygame/keyconstants.rb +237 -0
  44. data/lib/rubygame/mediabag.rb +94 -0
  45. data/lib/rubygame/queue.rb +288 -0
  46. data/lib/rubygame/rect.rb +614 -0
  47. data/lib/rubygame/sfont.rb +223 -0
  48. data/lib/rubygame/sprite.rb +477 -0
  49. data/samples/FreeSans.ttf +0 -0
  50. data/samples/GPL.txt +340 -0
  51. data/samples/README +40 -0
  52. data/samples/chimp.bmp +0 -0
  53. data/samples/chimp.rb +313 -0
  54. data/samples/demo_gl.rb +151 -0
  55. data/samples/demo_gl_tex.rb +197 -0
  56. data/samples/demo_music.rb +75 -0
  57. data/samples/demo_rubygame.rb +279 -0
  58. data/samples/demo_sfont.rb +52 -0
  59. data/samples/demo_ttf.rb +193 -0
  60. data/samples/demo_utf8.rb +53 -0
  61. data/samples/fist.bmp +0 -0
  62. data/samples/load_and_blit.rb +22 -0
  63. data/samples/panda.png +0 -0
  64. data/samples/punch.wav +0 -0
  65. data/samples/ruby.png +0 -0
  66. data/samples/term16.png +0 -0
  67. data/samples/whiff.wav +0 -0
  68. metadata +123 -0
@@ -0,0 +1,41 @@
1
+ /*
2
+ * Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3
+ * Copyright (C) 2004-2007 John Croisant
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ */
20
+
21
+ #ifndef _RUBYGAME_SCREEN_H
22
+ #define _RUBYGAME_SCREEN_H
23
+
24
+ extern void Rubygame_Init_Screen();
25
+
26
+ extern VALUE cScreen;
27
+
28
+ extern VALUE rbgm_screen_setmode(int, VALUE*, VALUE);
29
+ extern VALUE rbgm_screen_getsurface(VALUE);
30
+
31
+ extern VALUE rbgm_screen_getcaption(VALUE);
32
+ extern VALUE rbgm_screen_setcaption(VALUE, VALUE);
33
+
34
+ extern VALUE rbgm_screen_update(int, VALUE*, VALUE);
35
+ extern VALUE rbgm_screen_updaterects(VALUE, VALUE);
36
+ extern VALUE rbgm_screen_flip(VALUE);
37
+
38
+ extern VALUE rbgm_screen_getshowcursor(VALUE);
39
+ extern VALUE rbgm_screen_setshowcursor(VALUE, VALUE);
40
+
41
+ #endif
@@ -0,0 +1,152 @@
1
+ /*
2
+ * Code that is common to all Rubygame modules.
3
+ *--
4
+ * Rubygame -- Ruby code and bindings to SDL to facilitate game creation
5
+ * Copyright (C) 2004-2007 John Croisant
6
+ *
7
+ * This library is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU Lesser General Public
9
+ * License as published by the Free Software Foundation; either
10
+ * version 2.1 of the License, or (at your option) any later version.
11
+ *
12
+ * This library is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ * Lesser General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public
18
+ * License along with this library; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ *++
21
+ */
22
+
23
+ #include "rubygame_shared.h"
24
+
25
+ VALUE mRubygame;
26
+ VALUE cSurface;
27
+ VALUE cRect;
28
+ VALUE eSDLError;
29
+ SDL_Rect *make_rect(int, int, int, int);
30
+ int init_video_system();
31
+ void Init_rubygame_shared();
32
+
33
+ SDL_Rect *make_rect(int x, int y, int w, int h)
34
+ {
35
+ SDL_Rect *rect;
36
+ rect = (SDL_Rect *) malloc(sizeof(SDL_Rect));
37
+ rect->x = x;
38
+ rect->y = y;
39
+ rect->w = w;
40
+ rect->h = h;
41
+ return rect;
42
+ }
43
+
44
+ VALUE make_symbol(char *string)
45
+ {
46
+ return ID2SYM(rb_intern(string));
47
+ }
48
+
49
+ /* Take either nil, Numeric or an Array of Numerics, returns Uint32. */
50
+ Uint32 collapse_flags(VALUE vflags)
51
+ {
52
+ Uint32 flags = 0;
53
+ int i;
54
+
55
+ if( RTEST(vflags) )
56
+ {
57
+ switch( TYPE(vflags) ){
58
+ case T_ARRAY: {
59
+ int len = RARRAY(vflags)->len;
60
+ for(i=0; i < len; i++)
61
+ {
62
+ flags |= NUM2UINT( rb_ary_entry( vflags,i ) );
63
+ }
64
+ break;
65
+ }
66
+ case T_BIGNUM: {
67
+ flags = rb_big2uint( vflags );
68
+ break;
69
+ }
70
+ case T_FIXNUM: {
71
+ flags = NUM2UINT( vflags );
72
+ break;
73
+ }
74
+ default: {
75
+ rb_raise(rb_eArgError,"Wrong type for argument `flags' (wanted Number or Array).");
76
+ }
77
+ }
78
+ }
79
+
80
+ return flags;
81
+ }
82
+
83
+ VALUE convert_to_array(VALUE val)
84
+ {
85
+ VALUE v = rb_check_array_type(val);
86
+ if( TYPE(v) != T_ARRAY )
87
+ {
88
+ rb_raise(rb_eTypeError, "can't convert %s into Array",
89
+ rb_obj_classname(val));
90
+ }
91
+ return v;
92
+ }
93
+
94
+ /* --
95
+ *
96
+ * call-seq:
97
+ * init_video_system() -> int
98
+ *
99
+ * Initialize SDL's video subsystem.
100
+ * Return 0 (zero) on success, non-zero on failure.
101
+ *
102
+ * If it has already been initialized, return 0 immediately.
103
+ *
104
+ * ++
105
+ */
106
+ int init_video_system()
107
+ {
108
+ if( SDL_WasInit(SDL_INIT_VIDEO) == 0 )
109
+ {
110
+ return SDL_Init(SDL_INIT_VIDEO);
111
+ }
112
+ else
113
+ {
114
+ return 0;
115
+ }
116
+ }
117
+
118
+
119
+ void Init_rubygame_shared()
120
+ {
121
+
122
+ mRubygame = rb_define_module("Rubygame");
123
+
124
+ /* Rubygame::Surface class */
125
+ if( !rb_const_defined(mRubygame,rb_intern("Surface")) )
126
+ {
127
+ cSurface = rb_define_class_under(mRubygame,"Surface",rb_cObject);
128
+ }
129
+ else
130
+ {
131
+ cSurface = rb_const_get(mRubygame,rb_intern("Surface"));
132
+ }
133
+
134
+ /* Rubygame::SDLError class */
135
+ if( !rb_const_defined(mRubygame,rb_intern("SDLError")))
136
+ {
137
+ /* Indicates that an SDL function did not execute properly. */
138
+ eSDLError = rb_define_class_under(mRubygame,"SDLError",rb_eStandardError);
139
+ }
140
+ else
141
+ {
142
+ eSDLError = rb_const_get(mRubygame,rb_intern("SDLError"));
143
+ }
144
+
145
+ /* Rubygame::VERSIONS hash table */
146
+ if( !rb_const_defined(mRubygame, rb_intern("VERSIONS")))
147
+ {
148
+ /* A Hash containing the version s of rubygame and it's
149
+ * compile-time dependencies. */
150
+ rb_define_const(mRubygame,"VERSIONS",rb_hash_new());
151
+ }
152
+ }
@@ -0,0 +1,54 @@
1
+ /*
2
+ * Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3
+ * Copyright (C) 2004-2007 John Croisant
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ */
20
+
21
+ #ifndef _RUBYGAME_SHARED_H
22
+ #define _RUBYGAME_SHARED_H
23
+
24
+ #include <SDL.h>
25
+ #include <ruby.h>
26
+ #include <stdio.h>
27
+
28
+ /* General */
29
+ extern VALUE mRubygame;
30
+ extern VALUE eSDLError;
31
+ extern VALUE cSurface;
32
+ extern VALUE cRect;
33
+ extern SDL_Rect *make_rect(int, int, int, int);
34
+ extern VALUE make_symbol(char *);
35
+ extern Uint32 collapse_flags(VALUE);
36
+ extern VALUE convert_to_array(VALUE);
37
+ extern int init_video_system();
38
+ extern void Init_rubygame_shared();
39
+
40
+ /* Apparently it is not desirable to define these functions when
41
+ * using Micrsoft Visual C.
42
+ */
43
+ #ifndef _MSC_VER
44
+
45
+ static inline int max(int a, int b) {
46
+ return a > b ? a : b;
47
+ }
48
+ static inline int min(int a, int b) {
49
+ return a > b ? b : a;
50
+ }
51
+
52
+ #endif
53
+
54
+ #endif
@@ -0,0 +1,1107 @@
1
+ /*
2
+ * Rubygame binding to SDL Surface class.
3
+ *--
4
+ * Rubygame -- Ruby code and bindings to SDL to facilitate game creation
5
+ * Copyright (C) 2004-2007 John Croisant
6
+ *
7
+ * This library is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU Lesser General Public
9
+ * License as published by the Free Software Foundation; either
10
+ * version 2.1 of the License, or (at your option) any later version.
11
+ *
12
+ * This library is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ * Lesser General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public
18
+ * License along with this library; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ *++
21
+ */
22
+
23
+ #include "rubygame_shared.h"
24
+ #include "rubygame_surface.h"
25
+
26
+ void Rubygame_Init_Surface();
27
+
28
+ VALUE rbgm_surface_new(int, VALUE*, VALUE);
29
+
30
+ VALUE rbgm_surface_get_w(VALUE);
31
+ VALUE rbgm_surface_get_h(VALUE);
32
+ VALUE rbgm_surface_get_size(VALUE);
33
+
34
+ VALUE rbgm_surface_get_depth(VALUE);
35
+ VALUE rbgm_surface_get_flags(VALUE);
36
+ VALUE rbgm_surface_get_masks(VALUE);
37
+
38
+ VALUE rbgm_surface_get_alpha(VALUE);
39
+ VALUE rbgm_surface_set_alpha(int, VALUE*, VALUE);
40
+
41
+ VALUE rbgm_surface_get_colorkey(VALUE);
42
+ VALUE rbgm_surface_set_colorkey(int, VALUE*, VALUE);
43
+
44
+ VALUE rbgm_surface_blit(int, VALUE*, VALUE);
45
+
46
+ VALUE rbgm_surface_fill(int, VALUE*, VALUE);
47
+
48
+ VALUE rbgm_surface_getat(int, VALUE*, VALUE);
49
+
50
+ VALUE rbgm_surface_pixels(VALUE);
51
+
52
+ VALUE rbgm_surface_get_cliprect(VALUE);
53
+ VALUE rbgm_surface_set_cliprect(VALUE, VALUE);
54
+
55
+ VALUE rbgm_surface_convert(int, VALUE*, VALUE);
56
+ VALUE rbgm_surface_displayformat(VALUE);
57
+ VALUE rbgm_surface_displayformatalpha(VALUE);
58
+
59
+ VALUE rbgm_image_savebmp(VALUE, VALUE);
60
+
61
+ VALUE rbgm_transform_flip(VALUE, VALUE, VALUE);
62
+
63
+ /*
64
+ * call-seq:
65
+ * new(size, depth=0, flags=0) -> Surface
66
+ *
67
+ * Create and initialize a new Surface object.
68
+ *
69
+ * A Surface is a grid of image data which you blit (i.e. copy) onto other
70
+ * Surfaces. Since the Rubygame display is also a Surface (see the Screen
71
+ * class), Surfaces can be blit to the screen; this is the most common way
72
+ * to display images on the screen.
73
+ *
74
+ * This method may raise SDLError if the SDL video subsystem could
75
+ * not be initialized for some reason.
76
+ *
77
+ * This function takes these arguments:
78
+ * size:: requested surface size; an array of the form [width, height].
79
+ * depth:: requested color depth (in bits per pixel). If depth is 0 (default),
80
+ * automatically choose a color depth: either the depth of the Screen
81
+ * mode (if one has been set), or the greatest color depth available
82
+ * on the system.
83
+ * flags:: an Array or Bitwise-OR'd list of zero or more of the following
84
+ * flags (located in the Rubygame module, e.g. Rubygame::SWSURFACE).
85
+ * This argument may be omitted, in which case the Surface
86
+ * will be a normal software surface (this is not necessarily a bad
87
+ * thing).
88
+ * SWSURFACE:: (default) request a software surface.
89
+ * HWSURFACE:: request a hardware-accelerated surface (using a
90
+ * graphics card), if available. Creates a software
91
+ * surface if hardware surfaces are not available.
92
+ * SRCCOLORKEY:: request a colorkeyed surface. #set_colorkey will
93
+ * also enable colorkey as needed. For a description
94
+ * of colorkeys, see #set_colorkey.
95
+ * SRCALPHA:: request an alpha channel. #set_alpha will
96
+ * also enable alpha. as needed. For a description
97
+ * of alpha, see #alpha.
98
+ */
99
+ VALUE rbgm_surface_new(int argc, VALUE *argv, VALUE class)
100
+ {
101
+ VALUE self;
102
+ SDL_Surface *self_surf;
103
+ SDL_PixelFormat* pixformat;
104
+ Uint32 flags, Rmask, Gmask, Bmask, Amask;
105
+ int w, h, depth;
106
+ VALUE vsize, vdepth, vflags;
107
+
108
+ rb_scan_args(argc, argv, "12", &vsize, &vdepth, &vflags);
109
+
110
+ if( SDL_GetVideoSurface() )
111
+ {
112
+ /* Pixel format is retrieved from the video surface. */
113
+ pixformat = (SDL_GetVideoSurface())->format;
114
+ }
115
+ else
116
+ {
117
+ /* We can only get the system color depth when the video system
118
+ * has been initialized. */
119
+ if( init_video_system() == 0 )
120
+ {
121
+ pixformat = SDL_GetVideoInfo()->vfmt;
122
+ }
123
+ else
124
+ {
125
+ rb_raise(eSDLError,"Could not initialize SDL video subsystem.");
126
+ return Qnil;
127
+ }
128
+ }
129
+
130
+ Rmask = pixformat->Rmask;
131
+ Gmask = pixformat->Gmask;
132
+ Bmask = pixformat->Bmask;
133
+ Amask = pixformat->Amask;
134
+
135
+ if( !NIL_P(vdepth) && NUM2INT(vdepth) > 0 )
136
+ {
137
+ /* TODO: We might want to check that the requested depth makes sense. */
138
+ depth = NUM2INT(vdepth);
139
+ }
140
+ else
141
+ {
142
+ depth = pixformat->BitsPerPixel;
143
+ }
144
+
145
+
146
+ /* Get width and height for new surface from vsize */
147
+ vsize = convert_to_array(vsize);
148
+
149
+ if(RARRAY(vsize)->len >= 2)
150
+ {
151
+ w = NUM2INT(rb_ary_entry(vsize,0));
152
+ h = NUM2INT(rb_ary_entry(vsize,1));
153
+ }
154
+ else
155
+ rb_raise(rb_eArgError,"Array is too short for Surface size (%d for 2)",\
156
+ RARRAY(vsize)->len);
157
+
158
+ flags = collapse_flags(vflags); /* in rubygame_shared */
159
+
160
+ /* Finally, we can create the new Surface! Or try, anyway... */
161
+ self_surf = SDL_CreateRGBSurface(flags,w,h,depth,Rmask,Gmask,Bmask,Amask);
162
+
163
+ if( self_surf == NULL )
164
+ rb_raise(eSDLError,"Could not create new surface: %s",SDL_GetError());
165
+
166
+
167
+ /* Wrap the new surface in a crunchy candy VALUE shell. */
168
+ self = Data_Wrap_Struct( cSurface,0,SDL_FreeSurface,self_surf );
169
+ /* The default initialize() does nothing, but may be overridden. */
170
+ rb_obj_call_init(self,argc,argv);
171
+ return self;
172
+ }
173
+
174
+ /* :nodoc: */
175
+ VALUE rbgm_surface_initialize(int argc, VALUE *argv, VALUE self)
176
+ {
177
+ return self;
178
+ }
179
+
180
+
181
+ /*
182
+ * call-seq:
183
+ * width
184
+ * w
185
+ *
186
+ * Return the width (in pixels) of the surface.
187
+ */
188
+ VALUE rbgm_surface_get_w(VALUE self)
189
+ {
190
+ SDL_Surface *surf;
191
+ Data_Get_Struct(self, SDL_Surface, surf);
192
+ return INT2NUM(surf->w);
193
+ }
194
+
195
+ /*
196
+ * call-seq:
197
+ * height
198
+ * h
199
+ *
200
+ * Return the height (in pixels) of the surface.
201
+ */
202
+ VALUE rbgm_surface_get_h(VALUE self)
203
+ {
204
+ SDL_Surface *surf;
205
+ Data_Get_Struct(self, SDL_Surface, surf);
206
+ return INT2NUM(surf->h);
207
+ }
208
+
209
+ /* call-seq:
210
+ * size -> [w,h]
211
+ *
212
+ * Return the surface's width and height (in pixels) in an Array.
213
+ */
214
+ VALUE rbgm_surface_get_size(VALUE self)
215
+ {
216
+ SDL_Surface *surf;
217
+ Data_Get_Struct(self, SDL_Surface, surf);
218
+ return rb_ary_new3( 2, INT2NUM(surf->w), INT2NUM(surf->h) );
219
+ }
220
+
221
+ /* call-seq:
222
+ * depth
223
+ *
224
+ * Return the color depth (in bits per pixel) of the surface.
225
+ */
226
+ VALUE rbgm_surface_get_depth(VALUE self)
227
+ {
228
+ SDL_Surface *surf;
229
+ Data_Get_Struct(self, SDL_Surface, surf);
230
+ return UINT2NUM(surf->format->BitsPerPixel);
231
+ }
232
+
233
+ /* call-seq:
234
+ * flags
235
+ *
236
+ * Return any flags the surface was initialized with
237
+ * (as a bitwise OR'd integer).
238
+ */
239
+ VALUE rbgm_surface_get_flags(VALUE self)
240
+ {
241
+ SDL_Surface *surf;
242
+ Data_Get_Struct(self, SDL_Surface, surf);
243
+ return UINT2NUM(surf->flags);
244
+ }
245
+
246
+ /*
247
+ * call-seq:
248
+ * masks -> [r,g,b,a]
249
+ *
250
+ * Return the color masks [r,g,b,a] of the surface. Almost everyone can
251
+ * ignore this function. Color masks are used to separate an
252
+ * integer representation of a color into its seperate channels.
253
+ */
254
+ VALUE rbgm_surface_get_masks(VALUE self)
255
+ {
256
+ SDL_Surface *surf;
257
+ SDL_PixelFormat *format;
258
+
259
+ Data_Get_Struct(self, SDL_Surface, surf);
260
+ format = surf->format;
261
+ return rb_ary_new3(4,\
262
+ UINT2NUM(format->Rmask),\
263
+ UINT2NUM(format->Gmask),\
264
+ UINT2NUM(format->Bmask),\
265
+ UINT2NUM(format->Amask));
266
+ }
267
+
268
+ /*
269
+ * call-seq:
270
+ * alpha
271
+ *
272
+ * Return the per-surface alpha (opacity; non-transparency) of the surface.
273
+ * It can range from 0 (full transparent) to 255 (full opaque).
274
+ */
275
+ VALUE rbgm_surface_get_alpha(VALUE self)
276
+ {
277
+ SDL_Surface *surf;
278
+ Data_Get_Struct(self, SDL_Surface, surf);
279
+ return INT2NUM(surf->format->alpha);
280
+ }
281
+
282
+ /*
283
+ * call-seq:
284
+ * set_alpha(alpha, flags=Rubygame::SRC_ALPHA)
285
+ *
286
+ * Set the per-surface alpha (opacity; non-transparency) of the surface.
287
+ *
288
+ * This function takes these arguments:
289
+ * alpha:: requested opacity of the surface. Alpha must be from 0
290
+ * (fully transparent) to 255 (fully opaque).
291
+ * flags:: 0 or Rubygame::SRC_ALPHA (default). Most people will want the
292
+ * default, in which case this argument can be omitted. For advanced
293
+ * users: this flag affects the surface as described in the docs for
294
+ * the SDL C function, SDL_SetAlpha.
295
+ */
296
+ VALUE rbgm_surface_set_alpha(int argc, VALUE *argv, VALUE self)
297
+ {
298
+ SDL_Surface *surf;
299
+ Uint8 alpha;
300
+ Uint32 flags = SDL_SRCALPHA;
301
+ VALUE valpha, vflags;
302
+
303
+ rb_scan_args(argc, argv, "11", &valpha, &vflags);
304
+
305
+ if( !NIL_P(vflags) )
306
+ {
307
+ flags = NUM2UINT(vflags);
308
+ }
309
+
310
+ alpha = NUM2UINT(valpha);
311
+
312
+ Data_Get_Struct(self, SDL_Surface, surf);
313
+ if( SDL_SetAlpha(surf,flags,alpha) != 0 )
314
+ rb_raise(eSDLError, "%s", SDL_GetError());
315
+ return self;
316
+ }
317
+
318
+ /*
319
+ * call-seq:
320
+ * colorkey -> [r,g,b] or nil
321
+ *
322
+ * Return the colorkey of the surface in the form [r,g,b] (or +nil+ if there
323
+ * is no key). The colorkey of a surface is the exact color which will be
324
+ * ignored when the surface is blitted, effectively turning that color
325
+ * transparent. This is often used to make a blue (for example) background
326
+ * on an image seem transparent.
327
+ */
328
+ VALUE rbgm_surface_get_colorkey( VALUE self )
329
+ {
330
+ SDL_Surface *surf;
331
+ Uint32 colorkey;
332
+ Uint8 r,g,b;
333
+
334
+ Data_Get_Struct(self, SDL_Surface, surf);
335
+ colorkey = surf->format->colorkey;
336
+ if((int *)colorkey == NULL)
337
+ return Qnil;
338
+ SDL_GetRGB(colorkey, surf->format, &r, &g, &b);
339
+ return rb_ary_new3(3,UINT2NUM(r),UINT2NUM(g),UINT2NUM(b));
340
+ }
341
+
342
+ /*
343
+ * call-seq:
344
+ * set_colorkey(color,flags=0)
345
+ *
346
+ * Set the colorkey of the surface. See Surface#colorkey for a description
347
+ * of colorkeys.
348
+ *
349
+ * This method takes these arguments:
350
+ * color:: color to use as the key, in the form [r,g,b]. Can be +nil+ to
351
+ * un-set the colorkey.
352
+ * flags:: 0 or Rubygame::SRC_COLORKEY (default) or
353
+ * Rubygame::SRC_COLORKEY|Rubygame::SDL_RLEACCEL. Most people will
354
+ * want the default, in which case this argument can be omitted. For
355
+ * advanced users: this flag affects the surface as described in the
356
+ * docs for the SDL C function, SDL_SetColorkey.
357
+ */
358
+ VALUE rbgm_surface_set_colorkey( int argc, VALUE *argv, VALUE self)
359
+ {
360
+ SDL_Surface *surf;
361
+ Uint32 color;
362
+ Uint32 flags;
363
+ Uint8 r,g,b;
364
+ VALUE vcolor, vflags;
365
+
366
+ Data_Get_Struct(self, SDL_Surface, surf);
367
+
368
+ rb_scan_args(argc, argv, "11", &vcolor, &vflags);
369
+
370
+ if( !NIL_P(vflags) )
371
+ {
372
+ flags = NUM2UINT(vflags);
373
+ }
374
+ else
375
+ {
376
+ flags = SDL_SRCCOLORKEY;
377
+ }
378
+
379
+
380
+ if( RTEST(vcolor) )
381
+ {
382
+ vcolor = convert_to_array(vcolor);
383
+ r = NUM2UINT(rb_ary_entry(vcolor,0));
384
+ g = NUM2UINT(rb_ary_entry(vcolor,1));
385
+ b = NUM2UINT(rb_ary_entry(vcolor,2));
386
+ color = SDL_MapRGB(surf->format, r,g,b);
387
+ }
388
+ else
389
+ {
390
+ flags = 0;
391
+ color = 0;
392
+ }
393
+
394
+ if(SDL_SetColorKey(surf,flags,color)!=0)
395
+ rb_raise(eSDLError,"could not set colorkey: %s",SDL_GetError());
396
+ return self;
397
+ }
398
+
399
+ /*
400
+ * call-seq:
401
+ * blit(target,dest,source=nil) -> Rect
402
+ *
403
+ * Blit (copy) all or part of the surface's image to another surface,
404
+ * at a given position. Returns a Rect representing the area of
405
+ * +target+ which was affected by the blit.
406
+ *
407
+ * This method takes these arguments:
408
+ * target:: the target Surface on which to paste the image.
409
+ * dest:: the coordinates of the top-left corner of the blit. Affects the
410
+ * area of +other+ the image data is /pasted/ over.
411
+ * Can also be a Rect or an Array larger than 2, but
412
+ * width and height will be ignored.
413
+ * source:: a Rect representing the area of the source surface to get data
414
+ * from. Affects where the image data is /copied/ from.
415
+ * Can also be an Array of no less than 4 values.
416
+ */
417
+ VALUE rbgm_surface_blit(int argc, VALUE *argv, VALUE self)
418
+ {
419
+ int left, top, right, bottom;
420
+ int blit_x,blit_y,blit_w,blit_h;
421
+ //int dest_x,dest_y,dest_w,dest_h;
422
+ int src_x,src_y,src_w,src_h;
423
+ VALUE returnrect;
424
+ SDL_Surface *src, *dest;
425
+ SDL_Rect *src_rect, *blit_rect;
426
+
427
+ VALUE vtarget, vdest, vsource;
428
+
429
+ rb_scan_args( argc, argv, "21", &vtarget, &vdest, &vsource );
430
+
431
+ Data_Get_Struct(self, SDL_Surface, src);
432
+ Data_Get_Struct(vtarget, SDL_Surface, dest);
433
+
434
+ vdest = convert_to_array(vdest);
435
+ blit_x = NUM2INT(rb_ary_entry(vdest,0));
436
+ blit_y = NUM2INT(rb_ary_entry(vdest,1));
437
+
438
+ /* did we get a src_rect argument or not? */
439
+ if( !NIL_P(vsource) )
440
+ {
441
+ /* it might be good to check that it's actually a rect */
442
+ vsource = convert_to_array(vsource);
443
+ src_x = NUM2INT( rb_ary_entry(vsource,0) );
444
+ src_y = NUM2INT( rb_ary_entry(vsource,1) );
445
+ src_w = NUM2INT( rb_ary_entry(vsource,2) );
446
+ src_h = NUM2INT( rb_ary_entry(vsource,3) );
447
+ }
448
+ else
449
+ {
450
+ src_x = 0;
451
+ src_y = 0;
452
+ src_w = src->w;
453
+ src_h = src->h;
454
+ }
455
+ src_rect = make_rect( src_x, src_y, src_w, src_h );
456
+
457
+ /* experimental (broken) rectangle cropping code */
458
+ /* crop if it went off left/top/right/bottom */
459
+ //left = max(blit_x,0);
460
+ //top = max(blit_y,0);
461
+ //right = min(blit_x+src_w,dest->w);
462
+ //bottom = min(blit_y+src_h,dest->h);
463
+
464
+ left = blit_x;
465
+ top = blit_y;
466
+ right = blit_x+src_w;
467
+ bottom = blit_y+src_h;
468
+
469
+ //blit_w = min(blit_x+blit_w,dest->w) - max(blit_x,0);
470
+ //blit_h = min(blit_y+blit_h,dest->h) - max(blit_y,0);
471
+ blit_w = right - left;
472
+ blit_h = bottom - top;
473
+
474
+ blit_rect = make_rect( left, top, blit_w, blit_h );
475
+
476
+ SDL_BlitSurface(src,src_rect,dest,blit_rect);
477
+
478
+ returnrect = rb_funcall(cRect,rb_intern("new"),4,
479
+ INT2NUM(left),INT2NUM(top),\
480
+ INT2NUM(blit_w),INT2NUM(blit_h));
481
+
482
+ free(blit_rect);
483
+ free(src_rect);
484
+ return returnrect;
485
+ }
486
+
487
+ /*
488
+ * call-seq:
489
+ * fill(color,rect=nil)
490
+ *
491
+ * Fill all or part of a Surface with a color.
492
+ *
493
+ * This method takes these arguments:
494
+ * color:: color to fill with, in the form +[r,g,b]+ or +[r,g,b,a]+ (for
495
+ * partially transparent fills).
496
+ * rect:: a Rubygame::Rect representing the area of the surface to fill
497
+ * with color. Omit to fill the entire surface.
498
+ */
499
+ VALUE rbgm_surface_fill( int argc, VALUE *argv, VALUE self )
500
+ {
501
+ SDL_Surface *surf;
502
+ SDL_Rect *rect;
503
+ Uint32 color;
504
+ Uint8 r,g,b,a;
505
+ VALUE vcolor, vrect;
506
+
507
+ Data_Get_Struct(self, SDL_Surface, surf);
508
+
509
+ rb_scan_args(argc, argv, "11", &vcolor, &vrect);
510
+
511
+ vcolor = convert_to_array(vcolor);
512
+ r = NUM2UINT(rb_ary_entry(vcolor,0));
513
+ g = NUM2UINT(rb_ary_entry(vcolor,1));
514
+ b = NUM2UINT(rb_ary_entry(vcolor,2));
515
+ /* if the array is larger than [R,G,B], it should be [R,G,B,A] */
516
+ if(RARRAY(vcolor)->len > 3)
517
+ {
518
+ a = NUM2UINT(rb_ary_entry(vcolor,3));
519
+ color = SDL_MapRGBA(surf->format, r,g,b,a);
520
+ }
521
+ else
522
+ {
523
+ color = SDL_MapRGB(surf->format, r,g,b);
524
+ }
525
+
526
+ if( NIL_P(vrect) )
527
+ {
528
+ SDL_FillRect(surf,NULL,color);
529
+ }
530
+ else
531
+ {
532
+ vrect = convert_to_array(vrect);
533
+
534
+ rect = make_rect(\
535
+ NUM2INT(rb_ary_entry(vrect,0)),\
536
+ NUM2INT(rb_ary_entry(vrect,1)),\
537
+ NUM2INT(rb_ary_entry(vrect,2)),\
538
+ NUM2INT(rb_ary_entry(vrect,3))\
539
+ );
540
+ SDL_FillRect(surf,rect,color);
541
+ free(rect);
542
+ }
543
+
544
+ return self;
545
+ }
546
+
547
+ /*
548
+ * call-seq:
549
+ * get_at(x,y)
550
+ * get_at([x,y]) # deprecated
551
+ *
552
+ * Return the color [r,g,b,a] of the pixel at the given coordinate.
553
+ *
554
+ * Raises IndexError if the coordinates are out of bounds.
555
+ */
556
+ VALUE rbgm_surface_getat( int argc, VALUE *argv, VALUE self )
557
+ {
558
+ SDL_Surface *surf;
559
+ int x, y, locked;
560
+ Uint32 color;
561
+ Uint8 *pixels, *pix;
562
+ Uint8 r,g,b,a;
563
+ VALUE vx, vy;
564
+
565
+ Data_Get_Struct(self, SDL_Surface, surf);
566
+
567
+ rb_scan_args(argc, argv, "11", &vx, &vy);
568
+
569
+ /* Still support passing position as an Array... for now. */
570
+ switch( TYPE(vx) )
571
+ {
572
+ case T_ARRAY: {
573
+ x = NUM2INT( rb_ary_entry(vx,0) );
574
+ y = NUM2INT( rb_ary_entry(vx,1) );
575
+ break;
576
+ }
577
+ default: {
578
+ x = NUM2INT(vx);
579
+ y = NUM2INT(vy);
580
+ break;
581
+ }
582
+ }
583
+
584
+ if( x < 0 || x > surf->w )
585
+ rb_raise(rb_eIndexError,"x index out of bounds (%d, min 0, max %d)",\
586
+ x,surf->w);
587
+ if( y < 0 || y > surf->h )
588
+ rb_raise(rb_eIndexError,"y index out of bounds (%d, min 0, max %d)",\
589
+ y,surf->h);
590
+
591
+ locked = 0;
592
+ /* lock surface */
593
+ if(SDL_MUSTLOCK(surf))
594
+ {
595
+ if(SDL_LockSurface(surf)==0)
596
+ locked += 1;
597
+ else
598
+ rb_raise(eSDLError,"could not lock surface: %s",SDL_GetError());
599
+ }
600
+
601
+ /* borrowed from pygame */
602
+ pixels = (Uint8 *) surf->pixels;
603
+
604
+ switch(surf->format->BytesPerPixel)
605
+ {
606
+ case 1:
607
+ color = (Uint32)*((Uint8 *)(pixels + y * surf->pitch) + x);
608
+ break;
609
+ case 2:
610
+ color = (Uint32)*((Uint16 *)(pixels + y * surf->pitch) + x);
611
+ break;
612
+ case 3:
613
+ pix = ((Uint8 *)(pixels + y * surf->pitch) + x * 3);
614
+ #if SDL_BYTEORDER == SDL_LIL_ENDIAN
615
+ color = (pix[0]) + (pix[1]<<8) + (pix[2]<<16);
616
+ #else
617
+ color = (pix[2]) + (pix[1]<<8) + (pix[0]<<16);
618
+ #endif
619
+ break;
620
+ default: /*case 4:*/
621
+ color = *((Uint32*)(pixels + y * surf->pitch) + x);
622
+ break;
623
+ }
624
+
625
+ /* end borrowed from pygame */
626
+
627
+ /* recursively unlock surface*/
628
+ while(locked>1)
629
+ {
630
+ SDL_UnlockSurface(surf);
631
+ locked -= 1;
632
+ }
633
+
634
+ if((int *)color == NULL)
635
+ {
636
+ VALUE zero = INT2NUM(0);
637
+ return rb_ary_new3(4,zero,zero,zero,zero);
638
+ }
639
+
640
+ SDL_GetRGBA(color, surf->format, &r, &g, &b, &a);
641
+ return rb_ary_new3(4,UINT2NUM(r),UINT2NUM(g),UINT2NUM(b),UINT2NUM(a));
642
+ }
643
+
644
+ /*
645
+ * call-seq:
646
+ * pixels -> String
647
+ *
648
+ * Return a string of pixel data for the Surface. Most users will not
649
+ * need to use this method. If you want to convert a Surface into an
650
+ * OpenGL texture, pass the returned string to the TexImage2D method
651
+ * of the ruby-opengl library. (See samples/demo_gl_tex.rb for an example.)
652
+ *
653
+ * (Please note that the dimensions of OpenGL textures must be powers of 2
654
+ * (e.g. 64x128, 512x512), so if you want to use a Surface as an OpenGL
655
+ * texture, the Surface's dimensions must also be powers of 2!)
656
+ */
657
+ VALUE rbgm_surface_pixels( VALUE self )
658
+ {
659
+ SDL_Surface *surf;
660
+ Data_Get_Struct(self, SDL_Surface, surf);
661
+ return rb_str_new(surf->pixels, (long)surf->pitch * surf->h);
662
+ }
663
+
664
+ /*
665
+ * call-seq:
666
+ * clip -> Rect
667
+ *
668
+ * Return the clipping area for this Surface. See also #cliprect=.
669
+ *
670
+ * The clipping area of a Surface is the only part which can be drawn upon
671
+ * by other Surface's #blits. By default, the clipping area is the entire area
672
+ * of the Surface.
673
+ */
674
+ VALUE rbgm_surface_get_clip( VALUE self )
675
+ {
676
+ SDL_Rect rect;
677
+ SDL_Surface *surf;
678
+ Data_Get_Struct(self, SDL_Surface, surf);
679
+
680
+ SDL_GetClipRect(surf, &rect);
681
+
682
+ return rb_funcall(cRect,rb_intern("new"),4,
683
+ INT2NUM(rect.x),INT2NUM(rect.y),
684
+ INT2NUM(rect.w),INT2NUM(rect.h));
685
+ }
686
+
687
+ /*
688
+ * call-seq:
689
+ * clip = Rect or nil
690
+ *
691
+ * Set the current clipping area of the Surface. See also #cliprect.
692
+ *
693
+ * The clipping area of a Surface is the only part which can be drawn upon
694
+ * by other Surface's #blits. The clipping area will be clipped to the edges
695
+ * of the surface so that the clipping area for a Surface can never fall
696
+ * outside the edges of the Surface.
697
+ *
698
+ * By default, the clipping area is the entire area of the Surface.
699
+ * You may set clip to +nil+, which will reset the clipping area to cover
700
+ * the entire Surface.
701
+ */
702
+ VALUE rbgm_surface_set_clip( VALUE self, VALUE clip )
703
+ {
704
+ SDL_Rect *rect;
705
+ SDL_Surface *surf;
706
+ Data_Get_Struct(self, SDL_Surface, surf);
707
+
708
+
709
+ if( NIL_P(clip) )
710
+ {
711
+ SDL_SetClipRect(surf,NULL);
712
+ }
713
+ else
714
+ {
715
+ clip = convert_to_array(clip);
716
+ rect = make_rect(\
717
+ NUM2INT(rb_ary_entry(clip,0)),\
718
+ NUM2INT(rb_ary_entry(clip,1)),\
719
+ NUM2INT(rb_ary_entry(clip,2)),\
720
+ NUM2INT(rb_ary_entry(clip,3))\
721
+ );
722
+
723
+ SDL_SetClipRect(surf,rect);
724
+ }
725
+
726
+ return self;
727
+ }
728
+
729
+ /*
730
+ * call-seq:
731
+ * convert( other=nil, flags=nil ) -> Surface
732
+ *
733
+ * Copies the Surface to a new Surface with the pixel format of another
734
+ * Surface, for fast blitting. May raise SDLError if a problem occurs.
735
+ *
736
+ * This method takes these arguments:
737
+ * - other:: The Surface to match pixel format against. If +nil+, the
738
+ * display surface (i.e. Screen) is used, if available; if no
739
+ * display surface is available, raises SDLError.
740
+ * - flags:: An array of flags to pass when the new Surface is created.
741
+ * See Surface#new.
742
+ *
743
+ */
744
+ VALUE rbgm_surface_convert(int argc, VALUE *argv, VALUE self)
745
+ {
746
+ SDL_Surface *surf, *othersurf, *newsurf;
747
+ Uint32 flags = 0;
748
+ VALUE vother, vflags;
749
+
750
+ Data_Get_Struct(self, SDL_Surface, surf);
751
+
752
+ rb_scan_args(argc, argv, "02", &vother, &vflags );
753
+
754
+ if( !NIL_P(vother) )
755
+ {
756
+ Data_Get_Struct(vother, SDL_Surface, othersurf);
757
+ }
758
+ else
759
+ {
760
+ othersurf = SDL_GetVideoSurface();
761
+ if( othersurf == NULL )
762
+ {
763
+ rb_raise(eSDLError, "Cannot convert Surface with no target given and no Screen made: %s", SDL_GetError());
764
+ }
765
+ }
766
+
767
+ flags = collapse_flags(vflags); /* in rubygame_shared.c */
768
+
769
+ if( init_video_system() == 0 )
770
+ {
771
+ newsurf = SDL_ConvertSurface( surf, othersurf->format, flags );
772
+ }
773
+ else
774
+ {
775
+ newsurf = NULL;
776
+ }
777
+
778
+ if( newsurf == NULL )
779
+ {
780
+ rb_raise(eSDLError,\
781
+ "Could not convert the Surface: %s",\
782
+ SDL_GetError());
783
+ }
784
+
785
+ return Data_Wrap_Struct( cSurface,0,SDL_FreeSurface,newsurf );
786
+ }
787
+
788
+ /*
789
+ * call-seq:
790
+ * to_display() -> Surface
791
+ *
792
+ * Copies the Surface to a new Surface with the pixel format of the display,
793
+ * suitable for fast blitting to the display surface (i.e. Screen).
794
+ * May raise SDLError if a problem occurs.
795
+ *
796
+ * If you want to take advantage of hardware colorkey or alpha blit
797
+ * acceleration, you should set the colorkey and alpha value before calling
798
+ * this function.
799
+ *
800
+ */
801
+ VALUE rbgm_surface_dispform(VALUE self)
802
+ {
803
+ SDL_Surface *surf, *newsurf;
804
+ Data_Get_Struct(self, SDL_Surface, surf);
805
+
806
+ if( init_video_system() == 0 )
807
+ {
808
+ newsurf = SDL_DisplayFormat( surf );
809
+ }
810
+ else
811
+ {
812
+ newsurf = NULL;
813
+ }
814
+
815
+ if( newsurf == NULL )
816
+ {
817
+ rb_raise(eSDLError,\
818
+ "Could not convert the Surface to display format: %s",\
819
+ SDL_GetError());
820
+ }
821
+
822
+ return Data_Wrap_Struct( cSurface,0,SDL_FreeSurface,newsurf );
823
+ }
824
+
825
+ /*
826
+ * call-seq:
827
+ * to_display_alpha() -> Surface
828
+ *
829
+ * Like #to_display except the Surface has an extra channel for alpha (i.e.
830
+ * opacity). May raise SDLError if a problem occurs.
831
+ *
832
+ * This function can be used to convert a colorkey to an alpha channel, if the
833
+ * SRCCOLORKEY flag is set on the surface. The generated surface will then be
834
+ * transparent (alpha=0) where the pixels match the colorkey, and opaque
835
+ * (alpha=255) elsewhere.
836
+ */
837
+ VALUE rbgm_surface_dispformalpha(VALUE self)
838
+ {
839
+ SDL_Surface *surf, *newsurf;
840
+ Data_Get_Struct(self, SDL_Surface, surf);
841
+
842
+ if( init_video_system() == 0 )
843
+ {
844
+ newsurf = SDL_DisplayFormatAlpha( surf );
845
+ }
846
+ else
847
+ {
848
+ newsurf = NULL;
849
+ }
850
+
851
+ if( newsurf == NULL )
852
+ {
853
+ rb_raise(eSDLError,\
854
+ "Could not convert the Surface to display format with alpha channel: %s",\
855
+ SDL_GetError());
856
+ }
857
+
858
+ return Data_Wrap_Struct( cSurface,0,SDL_FreeSurface,newsurf );
859
+ }
860
+
861
+
862
+ /*
863
+ * call-seq:
864
+ * savebmp( filename ) -> nil
865
+ *
866
+ * Save the Surface as a Windows Bitmap (BMP) file with the given filename.
867
+ */
868
+ VALUE rbgm_image_savebmp( VALUE self, VALUE filename )
869
+ {
870
+ char *name;
871
+ SDL_Surface *surf;
872
+
873
+ name = StringValuePtr(filename);
874
+ Data_Get_Struct(self,SDL_Surface,surf);
875
+ if(SDL_SaveBMP(surf,name)!=0)
876
+ {
877
+ rb_raise(eSDLError,\
878
+ "Couldn't save surface to file %s: %s",name,SDL_GetError());
879
+ }
880
+ return Qnil;
881
+ }
882
+
883
+
884
+ /* --
885
+ * Borrowed from Pygame:
886
+ * ++
887
+ */
888
+ static SDL_Surface* newsurf_fromsurf(SDL_Surface* surf, int width, int height)
889
+ {
890
+ SDL_Surface* newsurf;
891
+
892
+ if(surf->format->BytesPerPixel <= 0 || surf->format->BytesPerPixel > 4)
893
+ rb_raise(eSDLError,"unsupported Surface bit depth for transform");
894
+
895
+ newsurf = SDL_CreateRGBSurface(surf->flags, width, height, surf->format->BitsPerPixel,
896
+ surf->format->Rmask, surf->format->Gmask, surf->format->Bmask, surf->format->Amask);
897
+ if(!newsurf)
898
+ rb_raise(eSDLError,"%s",SDL_GetError());
899
+
900
+ /* Copy palette, colorkey, etc info */
901
+ if(surf->format->BytesPerPixel==1 && surf->format->palette)
902
+ SDL_SetColors(newsurf, surf->format->palette->colors, 0, surf->format->palette->ncolors);
903
+ if(surf->flags & SDL_SRCCOLORKEY)
904
+ SDL_SetColorKey(newsurf, (surf->flags&SDL_RLEACCEL)|SDL_SRCCOLORKEY, surf->format->colorkey);
905
+
906
+ return newsurf;
907
+ }
908
+
909
+ /*
910
+ * call-seq:
911
+ * flip(horz, vert) -> Surface
912
+ *
913
+ * Flips the source surface horizontally (if +horz+ is true), vertically
914
+ * (if +vert+ is true), or both (if both are true). This operation is
915
+ * non-destructive; the original image can be perfectly reconstructed by
916
+ * flipping the resultant image again.
917
+ *
918
+ * This operation does NOT require SDL_gfx.
919
+ *
920
+ * A similar effect can (supposedly) be achieved by giving X or Y zoom
921
+ * factors of -1 to #rotozoom (only if compiled with SDL_gfx 2.0.13 or
922
+ * greater). Your mileage may vary.
923
+ */
924
+ VALUE rbgm_transform_flip(VALUE self, VALUE vhorz, VALUE vvert)
925
+ {
926
+ SDL_Surface *surf, *newsurf;
927
+ int xaxis, yaxis;
928
+
929
+ int loopx, loopy;
930
+ int pixsize, srcpitch, dstpitch;
931
+ Uint8 *srcpix, *dstpix;
932
+
933
+ xaxis = RTEST(vhorz);
934
+ yaxis = RTEST(vvert);
935
+
936
+ Data_Get_Struct(self,SDL_Surface,surf);
937
+
938
+ /* Borrowed from Pygame: */
939
+ newsurf = newsurf_fromsurf(surf, surf->w, surf->h);
940
+ if(!newsurf)
941
+ return Qnil;
942
+
943
+ pixsize = surf->format->BytesPerPixel;
944
+ srcpitch = surf->pitch;
945
+ dstpitch = newsurf->pitch;
946
+
947
+ SDL_LockSurface(newsurf);
948
+
949
+ srcpix = (Uint8*)surf->pixels;
950
+ dstpix = (Uint8*)newsurf->pixels;
951
+
952
+ if(!xaxis)
953
+ {
954
+ if(!yaxis)
955
+ {
956
+ for(loopy = 0; loopy < surf->h; ++loopy)
957
+ memcpy(dstpix+loopy*dstpitch, srcpix+loopy*srcpitch, surf->w*surf->format->BytesPerPixel);
958
+ }
959
+ else
960
+ {
961
+ for(loopy = 0; loopy < surf->h; ++loopy)
962
+ memcpy(dstpix+loopy*dstpitch, srcpix+(surf->h-1-loopy)*srcpitch, surf->w*surf->format->BytesPerPixel);
963
+ }
964
+ }
965
+ else /*if (xaxis)*/
966
+ {
967
+ if(yaxis)
968
+ {
969
+ switch(surf->format->BytesPerPixel)
970
+ {
971
+ case 1:
972
+ for(loopy = 0; loopy < surf->h; ++loopy) {
973
+ Uint8* dst = (Uint8*)(dstpix+loopy*dstpitch);
974
+ Uint8* src = ((Uint8*)(srcpix+(surf->h-1-loopy)*srcpitch)) + surf->w - 1;
975
+ for(loopx = 0; loopx < surf->w; ++loopx)
976
+ *dst++ = *src--;
977
+ }break;
978
+ case 2:
979
+ for(loopy = 0; loopy < surf->h; ++loopy) {
980
+ Uint16* dst = (Uint16*)(dstpix+loopy*dstpitch);
981
+ Uint16* src = ((Uint16*)(srcpix+(surf->h-1-loopy)*srcpitch)) + surf->w - 1;
982
+ for(loopx = 0; loopx < surf->w; ++loopx)
983
+ *dst++ = *src--;
984
+ }break;
985
+ case 4:
986
+ for(loopy = 0; loopy < surf->h; ++loopy) {
987
+ Uint32* dst = (Uint32*)(dstpix+loopy*dstpitch);
988
+ Uint32* src = ((Uint32*)(srcpix+(surf->h-1-loopy)*srcpitch)) + surf->w - 1;
989
+ for(loopx = 0; loopx < surf->w; ++loopx)
990
+ *dst++ = *src--;
991
+ }break;
992
+ case 3:
993
+ for(loopy = 0; loopy < surf->h; ++loopy) {
994
+ Uint8* dst = (Uint8*)(dstpix+loopy*dstpitch);
995
+ Uint8* src = ((Uint8*)(srcpix+(surf->h-1-loopy)*srcpitch)) + surf->w*3 - 3;
996
+ for(loopx = 0; loopx < surf->w; ++loopx)
997
+ {
998
+ dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2];
999
+ dst += 3;
1000
+ src -= 3;
1001
+ }
1002
+ }break;
1003
+ }
1004
+ }
1005
+ else
1006
+ {
1007
+ switch(surf->format->BytesPerPixel)
1008
+ {
1009
+ case 1:
1010
+ for(loopy = 0; loopy < surf->h; ++loopy) {
1011
+ Uint8* dst = (Uint8*)(dstpix+loopy*dstpitch);
1012
+ Uint8* src = ((Uint8*)(srcpix+loopy*srcpitch)) + surf->w - 1;
1013
+ for(loopx = 0; loopx < surf->w; ++loopx)
1014
+ *dst++ = *src--;
1015
+ }break;
1016
+ case 2:
1017
+ for(loopy = 0; loopy < surf->h; ++loopy) {
1018
+ Uint16* dst = (Uint16*)(dstpix+loopy*dstpitch);
1019
+ Uint16* src = ((Uint16*)(srcpix+loopy*srcpitch)) + surf->w - 1;
1020
+ for(loopx = 0; loopx < surf->w; ++loopx)
1021
+ *dst++ = *src--;
1022
+ }break;
1023
+ case 4:
1024
+ for(loopy = 0; loopy < surf->h; ++loopy) {
1025
+ Uint32* dst = (Uint32*)(dstpix+loopy*dstpitch);
1026
+ Uint32* src = ((Uint32*)(srcpix+loopy*srcpitch)) + surf->w - 1;
1027
+ for(loopx = 0; loopx < surf->w; ++loopx)
1028
+ *dst++ = *src--;
1029
+ }break;
1030
+ case 3:
1031
+ for(loopy = 0; loopy < surf->h; ++loopy) {
1032
+ Uint8* dst = (Uint8*)(dstpix+loopy*dstpitch);
1033
+ Uint8* src = ((Uint8*)(srcpix+loopy*srcpitch)) + surf->w*3 - 3;
1034
+ for(loopx = 0; loopx < surf->w; ++loopx)
1035
+ {
1036
+ dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2];
1037
+ dst += 3;
1038
+ src -= 3;
1039
+ }
1040
+ }break;
1041
+ }
1042
+ }
1043
+ }
1044
+
1045
+ SDL_UnlockSurface(newsurf);
1046
+ /* Thanks, Pygame :) */
1047
+
1048
+
1049
+ if(newsurf == NULL)
1050
+ rb_raise(eSDLError,"Could not flip surface: %s",SDL_GetError());
1051
+ return Data_Wrap_Struct(cSurface,0,SDL_FreeSurface,newsurf);
1052
+ }
1053
+
1054
+ /*
1055
+ * See rubygame_image.c for the Surface class overview docs.
1056
+ * I hate RDoc's C parser.
1057
+ *
1058
+ */
1059
+ void Rubygame_Init_Surface()
1060
+ {
1061
+
1062
+ #if 0
1063
+ mRubygame = rb_define_module("Rubygame");
1064
+ cSurface = rb_define_class_under(mRubygame,"Surface",rb_cObject);
1065
+ #endif
1066
+
1067
+ rb_define_singleton_method(cSurface,"new",rbgm_surface_new,-1);
1068
+ rb_define_method(cSurface,"initialize",rbgm_surface_initialize,-1);
1069
+ rb_define_method(cSurface,"w",rbgm_surface_get_w,0);
1070
+ rb_define_alias(cSurface,"width","w");
1071
+ rb_define_method(cSurface,"h",rbgm_surface_get_h,0);
1072
+ rb_define_alias(cSurface,"height","h");
1073
+ rb_define_method(cSurface,"size",rbgm_surface_get_size,0);
1074
+ rb_define_method(cSurface,"depth",rbgm_surface_get_depth,0);
1075
+ rb_define_method(cSurface,"flags",rbgm_surface_get_flags,0);
1076
+ rb_define_method(cSurface,"masks",rbgm_surface_get_masks,0);
1077
+ rb_define_method(cSurface,"alpha",rbgm_surface_get_alpha,0);
1078
+ rb_define_method(cSurface,"set_alpha",rbgm_surface_set_alpha,-1);
1079
+ rb_define_method(cSurface,"colorkey",rbgm_surface_get_colorkey,0);
1080
+ rb_define_method(cSurface,"set_colorkey",rbgm_surface_set_colorkey,-1);
1081
+ rb_define_method(cSurface,"blit",rbgm_surface_blit,-1);
1082
+ rb_define_method(cSurface,"fill",rbgm_surface_fill,-1);
1083
+ rb_define_method(cSurface,"get_at",rbgm_surface_getat,-1);
1084
+ rb_define_method(cSurface,"pixels",rbgm_surface_pixels,0);
1085
+ rb_define_method(cSurface,"clip",rbgm_surface_get_clip,0);
1086
+ rb_define_method(cSurface,"clip=",rbgm_surface_set_clip,1);
1087
+ rb_define_method(cSurface,"convert",rbgm_surface_convert,-1);
1088
+ rb_define_method(cSurface,"to_display",rbgm_surface_dispform,0);
1089
+ rb_define_method(cSurface,"to_display_alpha",rbgm_surface_dispformalpha,0);
1090
+ rb_define_method(cSurface,"savebmp",rbgm_image_savebmp,1);
1091
+ rb_define_method(cSurface,"flip",rbgm_transform_flip,2);
1092
+
1093
+
1094
+ /* Surface initialization flags */
1095
+ rb_define_const(mRubygame,"SWSURFACE",UINT2NUM(SDL_SWSURFACE));
1096
+ rb_define_const(mRubygame,"HWSURFACE",UINT2NUM(SDL_HWSURFACE));
1097
+ rb_define_const(mRubygame,"ASYNCBLIT",UINT2NUM(SDL_ASYNCBLIT));
1098
+ rb_define_const(mRubygame,"ANYFORMAT",UINT2NUM(SDL_ANYFORMAT));
1099
+ rb_define_const(mRubygame,"HWPALETTE",UINT2NUM(SDL_HWPALETTE));
1100
+ rb_define_const(mRubygame,"HWACCEL",UINT2NUM(SDL_HWACCEL));
1101
+ rb_define_const(mRubygame,"SRCCOLORKEY",UINT2NUM(SDL_SRCCOLORKEY));
1102
+ rb_define_const(mRubygame,"RLEACCELOK",UINT2NUM(SDL_RLEACCELOK));
1103
+ rb_define_const(mRubygame,"RLEACCEL",UINT2NUM(SDL_RLEACCEL));
1104
+ rb_define_const(mRubygame,"SRCALPHA",UINT2NUM(SDL_SRCALPHA));
1105
+ rb_define_const(mRubygame,"PREALLOC",UINT2NUM(SDL_PREALLOC));
1106
+
1107
+ }