ruby-sdl2 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,75 @@
1
+ require 'sdl2'
2
+
3
+ SpriteMotion = Struct.new(:position, :velocity)
4
+ WINDOW_W = 640
5
+ WINDOW_H = 480
6
+ NUM_SPRITES = 100
7
+ MAX_SPEED = 1
8
+
9
+ def load_sprite(filename, renderer)
10
+ bitmap = SDL2::Surface.load_bmp(filename)
11
+ bitmap.color_key = bitmap.pixel(0, 0)
12
+ sprite = renderer.create_texture_from(bitmap)
13
+ bitmap.destroy
14
+
15
+ sprite
16
+ end
17
+
18
+ def move_sprite(motions, renderer, sprite)
19
+ # draw a gray background
20
+ renderer.draw_color = [0xA0, 0xA0, 0xA0]
21
+ renderer.clear
22
+
23
+ sprite_w = sprite.w; sprite_h = sprite.h
24
+
25
+ motions.each do |m|
26
+ m.position.x += m.velocity.x
27
+ if m.position.x < 0 || m.position.x >= WINDOW_W - sprite_w
28
+ m.velocity.x *= -1
29
+ m.position.x += m.velocity.x
30
+ end
31
+
32
+ m.position.y += m.velocity.y
33
+ if m.position.y < 0 || m.position.y >= WINDOW_H - sprite_h
34
+ m.velocity.y *= -1
35
+ m.position.y += m.velocity.y
36
+ end
37
+
38
+ renderer.copy(sprite, nil, m.position)
39
+ end
40
+
41
+ renderer.present
42
+ end
43
+
44
+ def random_position(sprite_w, sprite_h)
45
+ SDL2::Rect[rand(WINDOW_W - sprite_w), rand(WINDOW_H - sprite_h), sprite_w, sprite_h]
46
+ end
47
+
48
+ def random_velocity
49
+ loop do
50
+ x = rand(MAX_SPEED*2+1) - MAX_SPEED
51
+ y = rand(MAX_SPEED*2+1) - MAX_SPEED
52
+ return SDL2::Point.new(x, y) if x != 0 || y != 0
53
+ end
54
+ end
55
+
56
+ window = SDL2::Window.create("testspritesimple", 0, 0, WINDOW_W, WINDOW_H, 0)
57
+ renderer = window.create_renderer(-1, 0)
58
+ sprite = load_sprite("icon.bmp", renderer)
59
+ sprite_w = sprite.w; sprite_h = sprite.h
60
+
61
+ motions = Array.new(NUM_SPRITES) do
62
+ SpriteMotion.new(random_position(sprite_w, sprite_h), random_velocity)
63
+ end
64
+
65
+ loop do
66
+ while event = SDL2::Event.poll
67
+ case event
68
+ when SDL2::Event::Quit, SDL2::Event::KeyDown
69
+ exit
70
+ end
71
+ end
72
+
73
+ move_sprite(motions, renderer, sprite)
74
+ sleep 0.01
75
+ end
@@ -0,0 +1,11 @@
1
+ require 'sdl2'
2
+
3
+ SDL2.init(SDL2::INIT_TIMER)
4
+
5
+ p SDL2.get_ticks
6
+ p SDL2.get_performance_counter
7
+ p SDL2.get_performance_frequency
8
+ SDL2.delay 50
9
+ p SDL2.get_ticks
10
+ p SDL2.get_performance_counter
11
+ p SDL2.get_performance_frequency
@@ -0,0 +1,12 @@
1
+ require 'sdl2'
2
+
3
+ p SDL2::LIBSDL_VERSION
4
+ p SDL2::LIBSDL_VERSION_NUMBER
5
+ p SDL2::LIBSDL_REVISION
6
+ p SDL2::LIBSDL_REVISION_NUMBER
7
+ p SDL2::LIBSDL_IMAGE_VERSION
8
+ p SDL2::LIBSDL_IMAGE_VERSION_NUMBER
9
+ p SDL2::LIBSDL_MIXER_VERSION
10
+ p SDL2::LIBSDL_MIXER_VERSION_NUMBER
11
+ p SDL2::LIBSDL_TTF_VERSION
12
+ p SDL2::LIBSDL_TTF_VERSION_NUMBER
@@ -0,0 +1,65 @@
1
+ require 'sdl2'
2
+ require "pp"
3
+
4
+ SDL2.init(SDL2::INIT_VIDEO)
5
+
6
+ pp SDL2::PixelFormat::FORMATS.map{|f| f.name}
7
+ p SDL2::PixelFormat::RGBA8888
8
+
9
+ p SDL2::Display.displays
10
+ SDL2::Display.displays.each{|display| p display.modes }
11
+ display = SDL2::Display.displays.first
12
+ print "curent mode: "; p display.current_mode
13
+ print "desktop mode: "; p display.desktop_mode
14
+ search_mode = SDL2::Display::Mode.new(SDL2::PixelFormat::UNKNOWN, 640, 480, 60)
15
+ puts "The mode closest to #{search_mode.inspect} is #{display.closest_mode(search_mode).inspect}"
16
+ print "bounds: "; p display.bounds
17
+ puts "current video driver: #{SDL2.current_video_driver}"
18
+
19
+ window = SDL2::Window.create("video info", 10, 10, 640, 480, 0)
20
+ renderer = window.create_renderer(-1, 0)
21
+ texture = renderer.load_texture("icon.bmp")
22
+
23
+ puts "window id: #{window.window_id}"
24
+ p SDL2::Window.all_windows
25
+ p window.display_mode
26
+ p window.display
27
+ print "window brightness: "; p window.brightness
28
+ print "window input grabbing: "; p window.input_is_grabbed?
29
+ print "window maximum size: "; p window.maximum_size
30
+ print "window minimum size: "; p window.minimum_size
31
+ print "window position: "; p window.position
32
+ print "window size: "; p window.size
33
+ print "window title: "; p window.title
34
+ print "window bordered: "; p window.bordered
35
+
36
+ p window.renderer
37
+ p renderer
38
+
39
+ p SDL2.video_drivers
40
+ p SDL2::Renderer.drivers_info
41
+ p renderer.info
42
+ p renderer.clip_rect
43
+ p renderer.logical_size
44
+ p renderer.scale
45
+ p renderer.viewport
46
+ p renderer.support_render_target?
47
+ p renderer.output_size
48
+
49
+ p renderer.info.texture_formats
50
+ renderer.info.texture_formats.each do |format|
51
+ p [format.format, format.name, format.type, format.order, format.layout, format.bpp, format.bytes_per_pixel,
52
+ format.indexed?, format.alpha?, format.fourcc?]
53
+
54
+ end
55
+
56
+ p texture
57
+ texture.destroy
58
+ p texture
59
+
60
+ p SDL2::ScreenSaver.enabled?
61
+ SDL2::ScreenSaver.disable
62
+ p SDL2::ScreenSaver.enabled?
63
+
64
+ renderer.present
65
+
data/timer.c ADDED
@@ -0,0 +1,63 @@
1
+ #include "rubysdl2_internal.h"
2
+ #include <SDL_timer.h>
3
+
4
+ /*
5
+ * @overload delay(ms)
6
+ * @param [Integer] ms the number of milliseconds to delay
7
+ *
8
+ * Wait a specified milliseconds.
9
+ *
10
+ * This function stops all ruby threads. If you want to keep running other
11
+ * threads, you should use Kernel.sleep instead of this function.
12
+ *
13
+ * @return [nil]
14
+ */
15
+ static VALUE SDL_s_delay(VALUE self, VALUE ms)
16
+ {
17
+ SDL_Delay(NUM2UINT(ms));
18
+ return Qnil;
19
+ }
20
+
21
+ /*
22
+ * Return the number of milliseconds since {SDL2.init} is called.
23
+ *
24
+ * @return [Integer] milliseconds in 32bit unsigned value.
25
+ */
26
+ static VALUE SDL_s_get_ticks(VALUE self)
27
+ {
28
+ return UINT2NUM(SDL_GetTicks());
29
+ }
30
+
31
+ /*
32
+ * Return the current value of the high resolution counter.
33
+ *
34
+ * This method is typically used for profiling.
35
+ *
36
+ * @return [Integer] the current counter value
37
+ * @see SDL2.get_performance_frequency
38
+ */
39
+ static VALUE SDL_s_get_performance_counter(VALUE self)
40
+ {
41
+ return ULL2NUM(SDL_GetPerformanceCounter());
42
+ }
43
+
44
+ /*
45
+ * Return the frequency (count per second) of the high resolution counter.
46
+ *
47
+ * @return [Integer] a platform-specific count per second.
48
+ * @see SDL2.get_performance_counter
49
+ */
50
+ static VALUE SDL_s_get_performance_frequency(VALUE self)
51
+ {
52
+ return ULL2NUM(SDL_GetPerformanceFrequency());
53
+ }
54
+
55
+ void rubysdl2_init_timer(void)
56
+ {
57
+ rb_define_module_function(mSDL2, "delay", SDL_s_delay, 1);
58
+ rb_define_module_function(mSDL2, "get_ticks", SDL_s_get_ticks, 0);
59
+ rb_define_module_function(mSDL2, "get_performance_counter",
60
+ SDL_s_get_performance_counter, 0);
61
+ rb_define_module_function(mSDL2, "get_performance_frequency",
62
+ SDL_s_get_performance_frequency,0);
63
+ }
data/ttf.c ADDED
@@ -0,0 +1,196 @@
1
+ #ifdef HAVE_SDL_TTF_H
2
+ #include "rubysdl2_internal.h"
3
+ #include <SDL_ttf.h>
4
+ #include <ruby/encoding.h>
5
+
6
+ VALUE cTTF;
7
+
8
+ #define TTF_ERROR() do { HANDLE_ERROR(SDL_SetError(TTF_GetError())); } while (0)
9
+ #define HANDLE_TTF_ERROR(code) \
10
+ do { if ((code) < 0) { TTF_ERROR(); } } while (0)
11
+
12
+ typedef struct TTF {
13
+ TTF_Font* font;
14
+ } TTF;
15
+
16
+ #define TTF_ATTRIBUTE(attr, capitalized_attr, ruby2c, c2ruby) \
17
+ static VALUE TTF_##attr(VALUE self) \
18
+ { \
19
+ return c2ruby(TTF_Get##capitalized_attr(Get_TTF_Font(self))); \
20
+ } \
21
+ static VALUE TTF_set_##attr(VALUE self, VALUE val) \
22
+ { \
23
+ TTF_Set##capitalized_attr(Get_TTF_Font(self), ruby2c(val)); \
24
+ return Qnil; \
25
+ }
26
+
27
+ #define TTF_ATTRIBUTE_INT(attr, capitalized_attr) \
28
+ TTF_ATTRIBUTE(attr, capitalized_attr, NUM2INT, INT2NUM)
29
+
30
+ #define TTF_ATTR_READER(attr, capitalized_attr, c2ruby) \
31
+ static VALUE TTF_##attr(VALUE self) \
32
+ { \
33
+ return c2ruby(TTF_Font##capitalized_attr(Get_TTF_Font(self))); \
34
+ }
35
+
36
+ static void TTF_free(TTF* f)
37
+ {
38
+ if (rubysdl2_is_active() && f->font)
39
+ TTF_CloseFont(f->font);
40
+ free(f);
41
+ }
42
+
43
+ static VALUE TTF_new(TTF_Font* font)
44
+ {
45
+ TTF* f = ALLOC(TTF);
46
+ f->font = font;
47
+ return Data_Wrap_Struct(cTTF, 0, TTF_free, f);
48
+ }
49
+
50
+ DEFINE_WRAPPER(TTF_Font, TTF, font, cTTF, "SDL2::TTF");
51
+
52
+ static VALUE TTF_s_init(VALUE self)
53
+ {
54
+ HANDLE_TTF_ERROR(TTF_Init());
55
+ return Qnil;
56
+ }
57
+
58
+ static VALUE TTF_s_open(int argc, VALUE* argv, VALUE self)
59
+ {
60
+ TTF_Font* font;
61
+ VALUE fname, ptsize, index;
62
+ rb_scan_args(argc, argv, "21", &fname, &ptsize, &index);
63
+
64
+ font = TTF_OpenFontIndex(StringValueCStr(fname), NUM2INT(ptsize),
65
+ index == Qnil ? 0 : NUM2LONG(index));
66
+ if (!font)
67
+ TTF_ERROR();
68
+
69
+ return TTF_new(font);
70
+ }
71
+
72
+ static VALUE TTF_destroy(VALUE self)
73
+ {
74
+ TTF* f = Get_TTF(self);
75
+ if (f->font)
76
+ TTF_CloseFont(f->font);
77
+ f->font = NULL;
78
+ return Qnil;
79
+ }
80
+
81
+ TTF_ATTRIBUTE_INT(style, FontStyle);
82
+ TTF_ATTRIBUTE_INT(outline, FontOutline);
83
+ TTF_ATTRIBUTE_INT(hinting, FontHinting);
84
+ TTF_ATTRIBUTE(kerning, FontKerning, RTEST, INT2BOOL);
85
+ TTF_ATTR_READER(height, Height, INT2FIX);
86
+ TTF_ATTR_READER(ascent, Ascent, INT2FIX);
87
+ TTF_ATTR_READER(descent, Descent, INT2FIX);
88
+ TTF_ATTR_READER(line_skip, LineSkip, INT2FIX);
89
+ TTF_ATTR_READER(num_faces, Faces, LONG2NUM);
90
+ TTF_ATTR_READER(face_is_fixed_width_p, FaceIsFixedWidth, INT2BOOL);
91
+ TTF_ATTR_READER(face_family_name, FaceFamilyName, utf8str_new_cstr);
92
+ TTF_ATTR_READER(face_style_name, FaceStyleName, utf8str_new_cstr);
93
+
94
+ static VALUE TTF_size_text(VALUE self, VALUE text)
95
+ {
96
+ int w, h;
97
+ text = rb_str_export_to_enc(text, rb_utf8_encoding());
98
+ HANDLE_TTF_ERROR(TTF_SizeUTF8(Get_TTF_Font(self), StringValueCStr(text), &w, &h));
99
+ return rb_ary_new3(2, INT2NUM(w), INT2NUM(h));
100
+ }
101
+
102
+ static SDL_Surface* render_solid(TTF_Font* font, const char* text, SDL_Color fg, SDL_Color bg)
103
+ {
104
+ return TTF_RenderUTF8_Solid(font, text, fg);
105
+ }
106
+
107
+ static SDL_Surface* render_blended(TTF_Font* font, const char* text, SDL_Color fg, SDL_Color bg)
108
+ {
109
+ return TTF_RenderUTF8_Blended(font, text, fg);
110
+ }
111
+
112
+ static VALUE render(SDL_Surface* (*renderer)(TTF_Font*, const char*, SDL_Color, SDL_Color),
113
+ VALUE font, VALUE text, VALUE fg, VALUE bg)
114
+ {
115
+ SDL_Surface* surface;
116
+ text = rb_str_export_to_enc(text, rb_utf8_encoding());
117
+ surface = renderer(Get_TTF_Font(font), StringValueCStr(text),
118
+ Array_to_SDL_Color(fg), Array_to_SDL_Color(bg));
119
+ if (!surface)
120
+ TTF_ERROR();
121
+
122
+ return Surface_new(surface);
123
+ }
124
+
125
+ static VALUE TTF_render_solid(VALUE self, VALUE text, VALUE fg)
126
+ {
127
+ return render(render_solid, self, text, fg, Qnil);
128
+ }
129
+
130
+ static VALUE TTF_render_shaded(VALUE self, VALUE text, VALUE fg, VALUE bg)
131
+ {
132
+ return render(TTF_RenderUTF8_Shaded, self, text, fg, bg);
133
+ }
134
+
135
+ static VALUE TTF_render_blended(VALUE self, VALUE text, VALUE fg)
136
+ {
137
+ return render(render_blended, self, text, fg, Qnil);
138
+ }
139
+
140
+ void rubysdl2_init_ttf(void)
141
+ {
142
+ cTTF = rb_define_class_under(mSDL2, "TTF", rb_cObject);
143
+ rb_undef_alloc_func(cTTF);
144
+
145
+ rb_define_singleton_method(cTTF, "init", TTF_s_init, 0);
146
+ rb_define_singleton_method(cTTF, "open", TTF_s_open, -1);
147
+ rb_define_method(cTTF, "destroy?", TTF_destroy_p, 0);
148
+ rb_define_method(cTTF, "destroy", TTF_destroy, 0);
149
+
150
+ #define DEFINE_TTF_ATTRIBUTE(attr) do { \
151
+ rb_define_method(cTTF, #attr, TTF_##attr, 0); \
152
+ rb_define_method(cTTF, #attr "=", TTF_set_##attr, 1); \
153
+ } while (0)
154
+
155
+ DEFINE_TTF_ATTRIBUTE(style);
156
+ DEFINE_TTF_ATTRIBUTE(outline);
157
+ DEFINE_TTF_ATTRIBUTE(hinting);
158
+ DEFINE_TTF_ATTRIBUTE(kerning);
159
+
160
+ #define DEFINE_TTF_ATTR_READER(attr) \
161
+ rb_define_method(cTTF, #attr, TTF_##attr, 0)
162
+
163
+ DEFINE_TTF_ATTR_READER(height);
164
+ DEFINE_TTF_ATTR_READER(ascent);
165
+ DEFINE_TTF_ATTR_READER(descent);
166
+ DEFINE_TTF_ATTR_READER(line_skip);
167
+ DEFINE_TTF_ATTR_READER(num_faces);
168
+ rb_define_method(cTTF, "face_is_fixed_width?", TTF_face_is_fixed_width_p, 0);
169
+ DEFINE_TTF_ATTR_READER(face_family_name);
170
+ DEFINE_TTF_ATTR_READER(face_style_name);
171
+
172
+ rb_define_method(cTTF, "size_text", TTF_size_text, 1);
173
+ rb_define_method(cTTF, "render_solid", TTF_render_solid, 2);
174
+ rb_define_method(cTTF, "render_shaded", TTF_render_shaded, 3);
175
+ rb_define_method(cTTF, "render_blended", TTF_render_blended, 2);
176
+
177
+ #define DEFINE_TTF_CONST(name) \
178
+ rb_define_const(cTTF, #name, INT2NUM((TTF_##name)))
179
+ DEFINE_TTF_CONST(STYLE_NORMAL);
180
+ DEFINE_TTF_CONST(STYLE_BOLD);
181
+ DEFINE_TTF_CONST(STYLE_ITALIC);
182
+ DEFINE_TTF_CONST(STYLE_UNDERLINE);
183
+ DEFINE_TTF_CONST(STYLE_STRIKETHROUGH);
184
+
185
+ DEFINE_TTF_CONST(HINTING_NORMAL);
186
+ DEFINE_TTF_CONST(HINTING_LIGHT);
187
+ DEFINE_TTF_CONST(HINTING_MONO);
188
+ DEFINE_TTF_CONST(HINTING_NONE);
189
+ }
190
+
191
+ #else /* HAVE_SDL_TTF_H */
192
+ void rubysdl2_init_ttf(void)
193
+ {
194
+ }
195
+ #endif /* HAVE_SDL_TTF_H */
196
+
@@ -0,0 +1,2935 @@
1
+ /* -*- mode: C -*- */
2
+ #include "rubysdl2_internal.h"
3
+ #include <SDL_video.h>
4
+ #include <SDL_version.h>
5
+ #include <SDL_render.h>
6
+ #include <SDL_messagebox.h>
7
+ #include <SDL_endian.h>
8
+ #include <ruby/encoding.h>
9
+
10
+ static VALUE cWindow;
11
+ static VALUE cDisplay;
12
+ static VALUE cDisplayMode;
13
+ static VALUE cRenderer;
14
+ static VALUE cTexture;
15
+ static VALUE cRect;
16
+ static VALUE cPoint;
17
+ static VALUE cSurface;
18
+ static VALUE cRendererInfo;
19
+ static VALUE cPixelFormat; /* NOTE: This is related to SDL_PixelFormatEnum, not SDL_PixelFormat */
20
+ static VALUE mScreenSaver;
21
+
22
+ static VALUE hash_windowid_to_window = Qnil;
23
+
24
+ struct Window;
25
+ struct Renderer;
26
+ struct Texture;
27
+
28
+ #ifdef DEBUG_GC
29
+ #define GC_LOG(args) fprintf args
30
+ #else
31
+ #define GC_LOG(args)
32
+ #endif
33
+
34
+ typedef struct Window {
35
+ SDL_Window* window;
36
+ int num_renderers;
37
+ int max_renderers;
38
+ struct Renderer** renderers;
39
+ } Window;
40
+
41
+ typedef struct Renderer {
42
+ SDL_Renderer* renderer;
43
+ int num_textures;
44
+ int max_textures;
45
+ struct Texture** textures;
46
+ int refcount;
47
+ } Renderer;
48
+
49
+ typedef struct Texture {
50
+ SDL_Texture* texture;
51
+ int refcount;
52
+ } Texture;
53
+
54
+ typedef struct Surface {
55
+ SDL_Surface* surface;
56
+ int need_to_free_pixels;
57
+ } Surface;
58
+
59
+ static void Renderer_free(Renderer*);
60
+ static void Window_destroy_internal(Window* w)
61
+ {
62
+ int i;
63
+ for (i=0; i<w->num_renderers; ++i)
64
+ Renderer_free(w->renderers[i]);
65
+ w->num_renderers = w->max_renderers = 0;
66
+ free(w->renderers);
67
+ w->renderers = NULL;
68
+ }
69
+
70
+ static void Window_free(Window* w)
71
+ {
72
+
73
+ GC_LOG((stderr, "Window free: %p\n", w));
74
+ Window_destroy_internal(w);
75
+ if (w->window && rubysdl2_is_active())
76
+ SDL_DestroyWindow(w->window);
77
+
78
+ free(w);
79
+ }
80
+
81
+ static VALUE Window_new(SDL_Window* window)
82
+ {
83
+ Window* w = ALLOC(Window);
84
+ w->window = window;
85
+ w->num_renderers = 0;
86
+ w->max_renderers = 4;
87
+ w->renderers = ALLOC_N(struct Renderer*, 4);
88
+ return Data_Wrap_Struct(cWindow, 0, Window_free, w);
89
+ }
90
+
91
+ DEFINE_GETTER(static, Window, cWindow, "SDL2::Window");
92
+ DEFINE_WRAP_GETTER(, SDL_Window, Window, window, "SDL2::Window");
93
+ DEFINE_DESTROY_P(static, Window, window);
94
+
95
+ static VALUE Display_new(int index)
96
+ {
97
+ VALUE display = rb_obj_alloc(cDisplay);
98
+ rb_iv_set(display, "@index", INT2NUM(index));
99
+ rb_iv_set(display, "@name", utf8str_new_cstr(SDL_GetDisplayName(index)));
100
+ return display;
101
+ }
102
+
103
+ static VALUE DisplayMode_s_allocate(VALUE klass)
104
+ {
105
+ SDL_DisplayMode* mode = ALLOC(SDL_DisplayMode);
106
+ mode->format = mode->w = mode->h = mode->refresh_rate = 0;
107
+ mode->driverdata = NULL;
108
+ return Data_Wrap_Struct(klass, 0, free, mode);
109
+ }
110
+
111
+ static VALUE DisplayMode_new(SDL_DisplayMode* mode)
112
+ {
113
+ VALUE display_mode = DisplayMode_s_allocate(cDisplayMode);
114
+ SDL_DisplayMode* m;
115
+ Data_Get_Struct(display_mode, SDL_DisplayMode, m);
116
+ *m = *mode;
117
+ return display_mode;
118
+ }
119
+
120
+ DEFINE_GETTER(static, SDL_DisplayMode, cDisplayMode, "SDL2::Display::Mode");
121
+
122
+ static void Texture_free(Texture*);
123
+ static void Renderer_destroy_internal(Renderer* r)
124
+ {
125
+ int i;
126
+ for (i=0; i<r->num_textures; ++i)
127
+ Texture_free(r->textures[i]);
128
+ free(r->textures);
129
+ r->textures = NULL;
130
+ r->max_textures = r->num_textures = 0;
131
+
132
+ if (r->renderer && rubysdl2_is_active()) {
133
+ SDL_DestroyRenderer(r->renderer);
134
+ }
135
+ r->renderer = NULL;
136
+ }
137
+
138
+ static void Renderer_free(Renderer* r)
139
+ {
140
+ GC_LOG((stderr, "Renderer free: %p (refcount=%d)\n", r, r->refcount));
141
+ Renderer_destroy_internal(r);
142
+
143
+ r->refcount--;
144
+ if (r->refcount == 0) {
145
+ free(r);
146
+ }
147
+ }
148
+
149
+ static void Window_attach_renderer(Window* w, Renderer* r)
150
+ {
151
+ if (w->num_renderers == w->max_renderers) {
152
+ w->max_renderers *= 2;
153
+ REALLOC_N(w->renderers, Renderer*, w->max_renderers);
154
+ }
155
+ w->renderers[w->num_renderers++] = r;
156
+ ++r->refcount;
157
+ }
158
+
159
+ static VALUE Renderer_new(SDL_Renderer* renderer, Window* w)
160
+ {
161
+ Renderer* r = ALLOC(Renderer);
162
+ r->renderer = renderer;
163
+ r->num_textures = 0;
164
+ r->max_textures = 16;
165
+ r->textures = ALLOC_N(Texture*, 16);
166
+ r->refcount = 1;
167
+ Window_attach_renderer(w, r);
168
+ return Data_Wrap_Struct(cRenderer, 0, Renderer_free, r);
169
+ }
170
+
171
+ DEFINE_WRAPPER(SDL_Renderer, Renderer, renderer, cRenderer, "SDL2::Renderer");
172
+
173
+ static void Texture_destroy_internal(Texture* t)
174
+ {
175
+ if (t->texture && rubysdl2_is_active()) {
176
+ SDL_DestroyTexture(t->texture);
177
+ }
178
+ t->texture = NULL;
179
+ }
180
+
181
+ static void Texture_free(Texture* t)
182
+ {
183
+ GC_LOG((stderr, "Texture free: %p (refcount=%d)\n", t, t->refcount));
184
+ Texture_destroy_internal(t);
185
+ t->refcount--;
186
+ if (t->refcount == 0) {
187
+ free(t);
188
+ }
189
+ }
190
+
191
+ static void Renderer_attach_texture(Renderer* r, Texture* t)
192
+ {
193
+ if (r->max_textures == r->num_textures) {
194
+ r->max_textures *= 2;
195
+ REALLOC_N(r->textures, Texture*, r->max_textures);
196
+ }
197
+ r->textures[r->num_textures++] = t;
198
+ ++t->refcount;
199
+ }
200
+
201
+ static VALUE Texture_new(SDL_Texture* texture, Renderer* r)
202
+ {
203
+ Texture* t = ALLOC(Texture);
204
+ t->texture = texture;
205
+ t->refcount = 1;
206
+ Renderer_attach_texture(r, t);
207
+ return Data_Wrap_Struct(cTexture, 0, Texture_free, t);
208
+ }
209
+
210
+ DEFINE_WRAPPER(SDL_Texture, Texture, texture, cTexture, "SDL2::Texture");
211
+
212
+
213
+ static void Surface_free(Surface* s)
214
+ {
215
+ GC_LOG((stderr, "Surface free: %p\n", s));
216
+ if (s->need_to_free_pixels)
217
+ free(s->surface->pixels);
218
+ if (s->surface && rubysdl2_is_active())
219
+ SDL_FreeSurface(s->surface);
220
+ free(s);
221
+ }
222
+
223
+ VALUE Surface_new(SDL_Surface* surface)
224
+ {
225
+ Surface* s = ALLOC(Surface);
226
+ s->surface = surface;
227
+ s->need_to_free_pixels = 0;
228
+ return Data_Wrap_Struct(cSurface, 0, Surface_free, s);
229
+ }
230
+
231
+ DEFINE_WRAPPER(SDL_Surface, Surface, surface, cSurface, "SDL2::Surface");
232
+
233
+ DEFINE_GETTER(, SDL_Rect, cRect, "SDL2::Rect");
234
+
235
+ DEFINE_GETTER(static, SDL_Point, cPoint, "SDL2::Point");
236
+
237
+ static VALUE PixelFormat_new(Uint32 format)
238
+ {
239
+ VALUE fmt = UINT2NUM(format);
240
+ return rb_class_new_instance(1, &fmt, cPixelFormat);
241
+ }
242
+
243
+ static VALUE RendererInfo_new(SDL_RendererInfo* info)
244
+ {
245
+ VALUE rinfo = rb_obj_alloc(cRendererInfo);
246
+ VALUE texture_formats = rb_ary_new();
247
+ unsigned int i;
248
+
249
+ rb_iv_set(rinfo, "@name", rb_usascii_str_new_cstr(info->name));
250
+ rb_iv_set(rinfo, "@texture_formats", texture_formats);
251
+ for (i=0; i<info->num_texture_formats; ++i)
252
+ rb_ary_push(texture_formats, PixelFormat_new(info->texture_formats[i]));
253
+ rb_iv_set(rinfo, "@max_texture_width", INT2NUM(info->max_texture_width));
254
+ rb_iv_set(rinfo, "@max_texture_height", INT2NUM(info->max_texture_height));
255
+
256
+ return rinfo;
257
+ }
258
+
259
+ SDL_Color Array_to_SDL_Color(VALUE ary)
260
+ {
261
+ SDL_Color color;
262
+ VALUE a;
263
+ if (ary == Qnil) {
264
+ color.r = color.g = color.b = 0; color.a = 255;
265
+ return color;
266
+ }
267
+
268
+ Check_Type(ary, T_ARRAY);
269
+ if (RARRAY_LEN(ary) != 3 && RARRAY_LEN(ary) != 4)
270
+ rb_raise(rb_eArgError, "wrong number of Array elements (%ld for 3 or 4)",
271
+ RARRAY_LEN(ary));
272
+ color.r = NUM2UCHAR(rb_ary_entry(ary, 0));
273
+ color.g = NUM2UCHAR(rb_ary_entry(ary, 1));
274
+ color.b = NUM2UCHAR(rb_ary_entry(ary, 2));
275
+ a = rb_ary_entry(ary, 3);
276
+ if (a == Qnil)
277
+ color.a = 255;
278
+ else
279
+ color.a = NUM2UCHAR(a);
280
+ return color;
281
+ }
282
+
283
+ /*
284
+ * Get the names of all video drivers.
285
+ *
286
+ * You can use the name as an argument of {.video_init}.
287
+ *
288
+ * @return [Array<String>]
289
+ */
290
+ static VALUE SDL2_s_video_drivers(VALUE self)
291
+ {
292
+ int num_drivers = HANDLE_ERROR(SDL_GetNumVideoDrivers());
293
+ int i;
294
+ VALUE drivers = rb_ary_new();
295
+ for (i=0; i<num_drivers; ++i)
296
+ rb_ary_push(drivers, rb_usascii_str_new_cstr(SDL_GetVideoDriver(i)));
297
+ return drivers;
298
+ }
299
+
300
+ /*
301
+ * Get the name of current video driver
302
+ *
303
+ * @return [String] the name of the current video driver
304
+ * @return [nil] when the video is not initialized
305
+ */
306
+ static VALUE SDL2_s_current_video_driver(VALUE self)
307
+ {
308
+ const char* name = SDL_GetCurrentVideoDriver();
309
+ if (name)
310
+ return utf8str_new_cstr(name);
311
+ else
312
+ return Qnil;
313
+ }
314
+
315
+ /*
316
+ * @overload video_init(driver_name)
317
+ * Initialize the video subsystem, specifying a video driver.
318
+ *
319
+ * {.init} cannot specify a video driver, so you need to use
320
+ * this method to specify a driver.
321
+ *
322
+ * @param driver_name [String]
323
+ * @return [nil]
324
+ *
325
+ * @see .init
326
+ */
327
+ static VALUE SDL2_s_video_init(VALUE self, VALUE driver_name)
328
+ {
329
+ HANDLE_ERROR(SDL_VideoInit(StringValueCStr(driver_name)));
330
+ return Qnil;
331
+ }
332
+
333
+ /*
334
+ * Document-class: SDL2::Window
335
+ *
336
+ * This class represents a window.
337
+ *
338
+ * If you want to create graphical application using Ruby/SDL, first you need to
339
+ * create a window.
340
+ *
341
+ * All of methods/class methods are available only after initializing video
342
+ * subsystem by {SDL2.init}.
343
+ *
344
+ * # Window Flags
345
+ *
346
+ * OR'd bits of the following constants represents window states.
347
+ * You can see a window state using {#flags} and create a window with a specified
348
+ * state using flag parameter of {.create}.
349
+ *
350
+ * * {SDL2::Window::FULLSCREEN} - fullscreen window
351
+ * * {SDL2::Window::FULLSCREEN_DESKTOP} -
352
+ * fullscreen window at the current desktop resolution
353
+ * * {SDL2::Window::OPENGL} - window usable with OpenGL context
354
+ * * {SDL2::Window::SHOWN} - window is visible
355
+ * * {SDL2::Window::HIDDEN} - window is not visible
356
+ * * {SDL2::Window::BORDERLESS} - no window decoration
357
+ * * {SDL2::Window::RESIZABLE} - window is resizable
358
+ * * {SDL2::Window::MINIMIZDED} - window is minimized
359
+ * * {SDL2::Window::MAXIMIZED} - window is maximized
360
+ * * {SDL2::Window::INPUT_GRABBED} - window has grabbed input focus
361
+ * * {SDL2::Window::INPUT_FOCUS} - window has input focus
362
+ * * {SDL2::Window::MOUSE_FOCUS} - window has mouse focus
363
+ * * {SDL2::Window::FOREIGN} - window is not created by SDL
364
+ * * {SDL2::Window::ALLOW_HIGHDPI} - window should be created in high-DPI mode if supported
365
+ * * {SDL2::Window::MOUSE_CAPTURE} - window has mouse captured
366
+ *
367
+ *
368
+ * @!method destroy?
369
+ * Return true if the window is already destroyed.
370
+ */
371
+
372
+ /*
373
+ * @overload create(title, x, y, w, h, flags)
374
+ * Create a window with the specified position (x,y), dimensions (w,h) and flags.
375
+ *
376
+ * @param [Integer] x the x position of the left-top of the window
377
+ * @param [Integer] y the y position of the left-top of the window
378
+ * @param [Integer] w the width of the window
379
+ * @param [Integer] h the height of the window
380
+ * @param [Integer] flags 0, or one or more [Window flag masks](#label-Flags) OR'd together
381
+ *
382
+ * @return [SDL2::Window] created window
383
+ *
384
+ */
385
+ static VALUE Window_s_create(VALUE self, VALUE title, VALUE x, VALUE y, VALUE w, VALUE h,
386
+ VALUE flags)
387
+ {
388
+ SDL_Window* window;
389
+ VALUE win;
390
+ title = rb_str_export_to_enc(title, rb_utf8_encoding());
391
+ window = SDL_CreateWindow(StringValueCStr(title),
392
+ NUM2INT(x), NUM2INT(y), NUM2INT(w), NUM2INT(h),
393
+ NUM2UINT(flags));
394
+ if (window == NULL)
395
+ HANDLE_ERROR(-1);
396
+
397
+ win = Window_new(window);
398
+ rb_hash_aset(hash_windowid_to_window, UINT2NUM(SDL_GetWindowID(window)), win);
399
+ return win;
400
+ }
401
+
402
+ /*
403
+ * Get all windows under SDL.
404
+ *
405
+ * @return [Hash<Integer => SDL2::Window>]
406
+ * the hash from window id to the {SDL2::Window} objects.
407
+ */
408
+ static VALUE Window_s_all_windows(VALUE self)
409
+ {
410
+ return rb_hash_dup(hash_windowid_to_window);
411
+ }
412
+
413
+ /*
414
+ * @overload find_by_id(id)
415
+ * Get the window from ID.
416
+ *
417
+ * @param id [Integer] the window id you want to find
418
+ * @return [SDL2::Window] the window associated with **id**
419
+ * @return [nil] when no window is associated with **id**
420
+ *
421
+ */
422
+ static VALUE Window_s_find_by_id(VALUE self, VALUE id)
423
+ {
424
+ return rb_hash_aref(hash_windowid_to_window, id);
425
+ }
426
+
427
+ VALUE find_window_by_id(Uint32 id)
428
+ {
429
+ return Window_s_find_by_id(Qnil, UINT2NUM(id));
430
+ }
431
+
432
+ /*
433
+ * @overload destroy
434
+ * Destroy window.
435
+ *
436
+ * You cannot call almost all methods after calling this method.
437
+ * The exception is {#destroy?}.
438
+ *
439
+ * @return [void]
440
+ */
441
+ static VALUE Window_destroy(VALUE self)
442
+ {
443
+ Window_destroy_internal(Get_Window(self));
444
+ return Qnil;
445
+ }
446
+
447
+ /*
448
+ * @overload create_renderer(index, flags)
449
+ * Create a 2D rendering context for a window.
450
+ *
451
+ * @param [Integer] index the index of the rendering driver to initialize,
452
+ * or -1 to initialize the first one supporting the requested flags
453
+ * @param [Integer] flags 0, or one or more [Renderer flag masks](SDL2) OR'd together;
454
+ *
455
+ * @return [SDL2::Renderer] the created renderer (rendering context)
456
+ */
457
+ static VALUE Window_create_renderer(VALUE self, VALUE index, VALUE flags)
458
+ {
459
+ SDL_Renderer* sdl_renderer;
460
+ VALUE renderer;
461
+ sdl_renderer = SDL_CreateRenderer(Get_SDL_Window(self), NUM2INT(index), NUM2UINT(flags));
462
+
463
+ if (sdl_renderer == NULL)
464
+ HANDLE_ERROR(-1);
465
+
466
+ renderer = Renderer_new(sdl_renderer, Get_Window(self));
467
+ rb_iv_set(self, "renderer", renderer);
468
+ return renderer;
469
+ }
470
+
471
+ /*
472
+ * @overload renderer
473
+ * Return the renderer associate with the window
474
+ *
475
+ * @return [SDL2::Renderer] the associated renderer
476
+ * @return [nil] if no renderer is created yet
477
+ */
478
+ static VALUE Window_renderer(VALUE self)
479
+ {
480
+ return rb_iv_get(self, "renderer");
481
+ }
482
+
483
+ /*
484
+ * Get the numeric ID of the window.
485
+ *
486
+ * @return [Integer]
487
+ */
488
+ static VALUE Window_window_id(VALUE self)
489
+ {
490
+ return UINT2NUM(SDL_GetWindowID(Get_SDL_Window(self)));
491
+ }
492
+
493
+ /*
494
+ * Get information about the window.
495
+ *
496
+ * @return [SDL2::Window::Mode]
497
+ */
498
+ static VALUE Window_display_mode(VALUE self)
499
+ {
500
+ SDL_DisplayMode mode;
501
+ HANDLE_ERROR(SDL_GetWindowDisplayMode(Get_SDL_Window(self), &mode));
502
+ return DisplayMode_new(&mode);
503
+ }
504
+
505
+ /*
506
+ * Get the display associated with the window.
507
+ *
508
+ * @return [SDL2::Display]
509
+ */
510
+ static VALUE Window_display(VALUE self)
511
+ {
512
+ int display_index = HANDLE_ERROR(SDL_GetWindowDisplayIndex(Get_SDL_Window(self)));
513
+ return Display_new(display_index);
514
+ }
515
+
516
+ /*
517
+ * Get the brightness (gamma correction) of the window.
518
+ *
519
+ * @return [Float] the brightness
520
+ * @see #brightness=
521
+ */
522
+ static VALUE Window_brightness(VALUE self)
523
+ {
524
+ return DBL2NUM(SDL_GetWindowBrightness(Get_SDL_Window(self)));
525
+ }
526
+
527
+ /*
528
+ * @overload brightness=(brightness)
529
+ * Set the brightness (gamma correction) of the window.
530
+ *
531
+ * @param brightness [Float] the brightness, 0.0 means complete dark and 1.0 means
532
+ * normal brightness.
533
+ * @return [brightness]
534
+ *
535
+ * @see #brightness
536
+ */
537
+ static VALUE Window_set_brightness(VALUE self, VALUE brightness)
538
+ {
539
+ HANDLE_ERROR(SDL_SetWindowBrightness(Get_SDL_Window(self), NUM2DBL(brightness)));
540
+ return brightness;
541
+ }
542
+
543
+ /*
544
+ * Get the [Window flag masks](#label-Window+Flags) of the window.
545
+ *
546
+ * @return [Integer] flags
547
+ * @see .create
548
+ */
549
+ static VALUE Window_flags(VALUE self)
550
+ {
551
+ return UINT2NUM(SDL_GetWindowFlags(Get_SDL_Window(self)));
552
+ }
553
+
554
+ static VALUE gamma_table_to_Array(Uint16 r[])
555
+ {
556
+ int i;
557
+ VALUE ary = rb_ary_new2(256);
558
+ for (i=0; i<256; ++i)
559
+ rb_ary_push(ary, UINT2NUM(r[i]));
560
+ return ary;
561
+ }
562
+
563
+ /*
564
+ * Get the gamma ramp for a window
565
+ *
566
+ * @return [Array<Array<Integer>>] the gamma ramp,
567
+ * return value is red, green, and blue gamma tables and each gamma table
568
+ * has 256 Integers of 0-65535.
569
+ *
570
+ */
571
+ static VALUE Window_gamma_ramp(VALUE self)
572
+ {
573
+ Uint16 r[256], g[256], b[256];
574
+ HANDLE_ERROR(SDL_GetWindowGammaRamp(Get_SDL_Window(self), r, g, b));
575
+ return rb_ary_new3(3,
576
+ gamma_table_to_Array(r),
577
+ gamma_table_to_Array(g),
578
+ gamma_table_to_Array(b));
579
+ }
580
+
581
+ /*
582
+ * @overload icon=(icon)
583
+ *
584
+ * Set the window icon.
585
+ *
586
+ * @param icon [SDL2::Surface] the icon for the window
587
+ * @return [icon]
588
+ */
589
+ static VALUE Window_set_icon(VALUE self, VALUE icon)
590
+ {
591
+ SDL_SetWindowIcon(Get_SDL_Window(self), Get_SDL_Surface(icon));
592
+ return icon;
593
+ }
594
+
595
+ /*
596
+ * Return true if the input is grabbed to the window.
597
+ *
598
+ * @see #input_is_grabbed=
599
+ */
600
+ static VALUE Window_input_is_grabbed_p(VALUE self)
601
+ {
602
+ return INT2BOOL(SDL_GetWindowGrab(Get_SDL_Window(self)));
603
+ }
604
+
605
+ /*
606
+ * @overload input_is_grabbed=(grabbed)
607
+ * Set the window's input grab mode.
608
+ *
609
+ * @param grabbed [Boolean] true to grub input, and false to release input
610
+ * @return [grabbed]
611
+ *
612
+ * @see #input_is_grabbed?
613
+ */
614
+ static VALUE Window_set_input_is_grabbed(VALUE self, VALUE grabbed)
615
+ {
616
+ SDL_SetWindowGrab(Get_SDL_Window(self), RTEST(grabbed));
617
+ return grabbed;
618
+ }
619
+
620
+ static VALUE Window_get_int_int(void (*func)(SDL_Window*, int*, int*), VALUE window)
621
+ {
622
+ int n, m;
623
+ func(Get_SDL_Window(window), &n, &m);
624
+ return rb_ary_new3(2, INT2NUM(n), INT2NUM(m));
625
+ }
626
+
627
+ static VALUE Window_set_int_int(void (*func)(SDL_Window*, int, int), VALUE window, VALUE val)
628
+ {
629
+ Check_Type(val, T_ARRAY);
630
+ if (RARRAY_LEN(val) != 2)
631
+ rb_raise(rb_eArgError, "Wrong array size (%ld for 2)", RARRAY_LEN(val));
632
+ func(Get_SDL_Window(window), NUM2INT(rb_ary_entry(val, 0)), NUM2INT(rb_ary_entry(val, 1)));
633
+ return Qnil;
634
+ }
635
+
636
+ /*
637
+ * Get the maximum size of the window's client area.
638
+ *
639
+ * @return [Integer,Integer] maximum width and maximum height.
640
+ *
641
+ * @see #maximum_size=
642
+ */
643
+ static VALUE Window_maximum_size(VALUE self)
644
+ {
645
+ return Window_get_int_int(SDL_GetWindowMaximumSize, self);
646
+ }
647
+
648
+ /*
649
+ * @overload maximum_size=(size)
650
+ * Set the maximum size of the window's client area.
651
+ *
652
+ * @param size [[Integer, Integer]] maximum width and maximum height,
653
+ * the both must be positive.
654
+ *
655
+ * @return [size]
656
+ *
657
+ * @see #maximum_size
658
+ */
659
+ static VALUE Window_set_maximum_size(VALUE self, VALUE max_size)
660
+ {
661
+ return Window_set_int_int(SDL_SetWindowMaximumSize, self, max_size);
662
+ }
663
+
664
+ /*
665
+ * Get the minimum size of the window's client area.
666
+ *
667
+ * @return [Integer,Integer] minimum width and minimum height.
668
+ *
669
+ * @see #minimum_size=
670
+ */
671
+ static VALUE Window_minimum_size(VALUE self)
672
+ {
673
+ return Window_get_int_int(SDL_GetWindowMinimumSize, self);
674
+ }
675
+
676
+ /*
677
+ * @overload minimum_size=(size)
678
+ * Set the minimum size of the window's client area.
679
+ *
680
+ * @param size [[Integer, Integer]] minimum width and minimum height,
681
+ * the both must be positive.
682
+ *
683
+ * @return [size]
684
+ *
685
+ * @see #minimum_size
686
+ */
687
+ static VALUE Window_set_minimum_size(VALUE self, VALUE min_size)
688
+ {
689
+ return Window_set_int_int(SDL_SetWindowMinimumSize, self, min_size);
690
+ }
691
+
692
+ /*
693
+ * Get the position of the window.
694
+ *
695
+ * @return [Integer,Integer] the x position and the y position
696
+ *
697
+ * @see #position=
698
+ */
699
+ static VALUE Window_position(VALUE self)
700
+ {
701
+ return Window_get_int_int(SDL_GetWindowPosition, self);
702
+ }
703
+
704
+ /*
705
+ * @overload position=(xy)
706
+ * Set the position of the window
707
+ *
708
+ * @param xy [[Integer, Integer]] the x position and the y position,
709
+ * {SDL2::Window::POS_CENTERED} and {SDL2::Window::POS_UNDEFINED}
710
+ * are available.
711
+ *
712
+ * @return [size]
713
+ *
714
+ * @see #position
715
+ */
716
+ static VALUE Window_set_position(VALUE self, VALUE xy)
717
+ {
718
+ return Window_set_int_int(SDL_SetWindowPosition, self, xy);
719
+ }
720
+
721
+ /*
722
+ * Get the size of the window.
723
+ *
724
+ * @return [[Integer, Integer]] the width and the height
725
+ *
726
+ * @see size=
727
+ */
728
+ static VALUE Window_size(VALUE self)
729
+ {
730
+ return Window_get_int_int(SDL_GetWindowSize, self);
731
+ }
732
+
733
+ /*
734
+ * @overload size=(size)
735
+ * Set the size of the window.
736
+ *
737
+ * @param wh [[Integer, Integer]] new width and new height
738
+ *
739
+ * @return [size]
740
+ *
741
+ * @see #size
742
+ */
743
+ static VALUE Window_set_size(VALUE self, VALUE size)
744
+ {
745
+ return Window_set_int_int(SDL_SetWindowSize, self, size);
746
+ }
747
+
748
+ /*
749
+ * Get the title of the window
750
+ *
751
+ * @return [String] the title, in UTF-8 encoding
752
+ *
753
+ * @see #title=
754
+ */
755
+ static VALUE Window_title(VALUE self)
756
+ {
757
+ return utf8str_new_cstr(SDL_GetWindowTitle(Get_SDL_Window(self)));
758
+ }
759
+
760
+ /*
761
+ * Return true if the window is bordered
762
+ *
763
+ * @return [Boolean]
764
+ *
765
+ * @see #bordered=
766
+ */
767
+ static VALUE Window_bordered(VALUE self)
768
+ {
769
+ return INT2BOOL(!(SDL_GetWindowFlags(Get_SDL_Window(self)) & SDL_WINDOW_BORDERLESS));
770
+ }
771
+
772
+ /*
773
+ * @overload bordered=(bordered)
774
+ * Set the border state of the window.
775
+ *
776
+ * @param bordered [Boolean] true for bordered window, anad false for
777
+ * borderless window
778
+ *
779
+ * @return [bordered]
780
+ *
781
+ * @see #bordered
782
+ */
783
+ static VALUE Window_set_bordered(VALUE self, VALUE bordered)
784
+ {
785
+ SDL_SetWindowBordered(Get_SDL_Window(self), RTEST(bordered));
786
+ return bordered;
787
+ }
788
+
789
+ /*
790
+ * @overload title=(title)
791
+ * Set the title of the window.
792
+ *
793
+ * @param title [String] the title
794
+ * @return [title]
795
+ *
796
+ * @see #title
797
+ */
798
+ static VALUE Window_set_title(VALUE self, VALUE title)
799
+ {
800
+ title = rb_str_export_to_enc(title, rb_utf8_encoding());
801
+ SDL_SetWindowTitle(Get_SDL_Window(self), StringValueCStr(title));
802
+ return Qnil;
803
+ }
804
+
805
+ /*
806
+ define(`SIMPLE_WINDOW_METHOD',`static VALUE Window_$2(VALUE self)
807
+ {
808
+ SDL_$1Window(Get_SDL_Window(self)); return Qnil;
809
+ }')
810
+ */
811
+ /*
812
+ * Show the window.
813
+ *
814
+ * @return [nil]
815
+ * @see #hide
816
+ */
817
+ SIMPLE_WINDOW_METHOD(Show, show);
818
+
819
+ /*
820
+ * Hide the window.
821
+ *
822
+ * @return [nil]
823
+ * @see #show
824
+ */
825
+ SIMPLE_WINDOW_METHOD(Hide, hide);
826
+
827
+ /*
828
+ * Maximize the window.
829
+ *
830
+ * @return [nil]
831
+ * @see #minimize
832
+ * @see #restore
833
+ */
834
+ SIMPLE_WINDOW_METHOD(Maximize, maximize);
835
+
836
+ /*
837
+ * Minimize the window.
838
+ *
839
+ * @return [nil]
840
+ * @see #maximize
841
+ * @see #restore
842
+ */
843
+ SIMPLE_WINDOW_METHOD(Minimize, minimize);
844
+
845
+ /*
846
+ * Raise the window above other windows and set the input focus.
847
+ *
848
+ * @return [nil]
849
+ */
850
+ SIMPLE_WINDOW_METHOD(Raise, raise);
851
+
852
+ /*
853
+ * Restore the size and position of a minimized or maixmized window.
854
+ *
855
+ * @return [nil]
856
+ * @see #minimize
857
+ * @see #maximize
858
+ */
859
+ SIMPLE_WINDOW_METHOD(Restore, restore);
860
+
861
+ /*
862
+ * Get the fullscreen stete of the window
863
+ *
864
+ * @return [Integer] 0 for window mode, SDL2::Window::FULLSCREEN for
865
+ * fullscreen mode, and SDL2::Window::FULLSCREEN_DESKTOP for fullscreen
866
+ * at the current desktop resolution.
867
+ *
868
+ * @see #fullscreen_mode=
869
+ * @see #flags
870
+ */
871
+ static VALUE Window_fullscreen_mode(VALUE self)
872
+ {
873
+ Uint32 flags = SDL_GetWindowFlags(Get_SDL_Window(self));
874
+ return UINT2NUM(flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_FULLSCREEN_DESKTOP));
875
+ }
876
+
877
+ /*
878
+ * @overload fullscreen_mode=(flag)
879
+ * Set the fullscreen state of the window
880
+ *
881
+ * @param flag [Integer] 0 for window mode, SDL2::Window::FULLSCREEN for
882
+ * fullscreen mode, and SDL2::Window::FULLSCREEN_DESKTOP for fullscreen
883
+ * at the current desktop resolution.
884
+ * @return [flag]
885
+ *
886
+ * @see #fullscreen_mode
887
+ */
888
+ static VALUE Window_set_fullscreen_mode(VALUE self, VALUE flags)
889
+ {
890
+ HANDLE_ERROR(SDL_SetWindowFullscreen(Get_SDL_Window(self), NUM2UINT(flags)));
891
+ return flags;
892
+ }
893
+
894
+
895
+ /*
896
+ * Get the size of the drawable region.
897
+ *
898
+ * @return [[Integer, Integer]] the width and height of the region
899
+ */
900
+ #if SDL_VERSION_ATLEAST(2,0,1)
901
+ static VALUE Window_gl_drawable_size(VALUE self)
902
+ {
903
+ int w, h;
904
+ SDL_GL_GetDrawableSize(Get_SDL_Window(self), &w, &h);
905
+ return rb_ary_new3(2, INT2NUM(w), INT2NUM(h));
906
+ }
907
+ #endif
908
+
909
+ /*
910
+ * Swap the OpenGL buffers for the window, if double buffering
911
+ * is supported.
912
+ *
913
+ * @return [nil]
914
+ */
915
+ static VALUE Window_gl_swap(VALUE self)
916
+ {
917
+ SDL_GL_SwapWindow(Get_SDL_Window(self));
918
+ return Qnil;
919
+ }
920
+
921
+ /* @return [String] inspection string */
922
+ static VALUE Window_inspect(VALUE self)
923
+ {
924
+ Window* w = Get_Window(self);
925
+ if (w->window)
926
+ return rb_sprintf("<%s:%p window_id=%d>",
927
+ rb_obj_classname(self), (void*)self, SDL_GetWindowID(w->window));
928
+ else
929
+ return rb_sprintf("<%s:%p (destroyed)>", rb_obj_classname(self), (void*)self);
930
+ }
931
+
932
+ /* @return [Hash] (GC) debug information */
933
+ static VALUE Window_debug_info(VALUE self)
934
+ {
935
+ Window* w = Get_Window(self);
936
+ VALUE info = rb_hash_new();
937
+ int num_active_renderers = 0;
938
+ int i;
939
+ rb_hash_aset(info, rb_str_new2("destroy?"), INT2BOOL(w->window == NULL));
940
+ rb_hash_aset(info, rb_str_new2("max_renderers"), INT2NUM(w->max_renderers));
941
+ rb_hash_aset(info, rb_str_new2("num_renderers"), INT2NUM(w->num_renderers));
942
+ for (i=0; i<w->num_renderers; ++i)
943
+ if (w->renderers[i]->renderer)
944
+ ++num_active_renderers;
945
+ rb_hash_aset(info, rb_str_new2("num_active_renderers"), INT2NUM(num_active_renderers));
946
+
947
+ return info;
948
+ }
949
+
950
+ /*
951
+ * Document-class: SDL2::Display
952
+ *
953
+ * This class represents displays, screens, or monitors.
954
+ *
955
+ * This means that if you use dual screen, {.displays} returns two displays.
956
+ *
957
+ * This class handles color depth, resolution, and refresh rate of displays.
958
+ *
959
+ */
960
+
961
+ /*
962
+ * Get all connected displays.
963
+ *
964
+ * @return [Array<SDL2::Display>]
965
+ *
966
+ */
967
+ static VALUE Display_s_displays(VALUE self)
968
+ {
969
+ int i;
970
+ int num_displays = HANDLE_ERROR(SDL_GetNumVideoDisplays());
971
+ VALUE displays = rb_ary_new2(num_displays);
972
+ for (i=0; i<num_displays; ++i)
973
+ rb_ary_push(displays, Display_new(i));
974
+ return displays;
975
+ }
976
+
977
+ static int Display_index_int(VALUE display)
978
+ {
979
+ return NUM2INT(rb_iv_get(display, "@index"));
980
+ }
981
+
982
+ /*
983
+ * Get available display modes of the display.
984
+ *
985
+ * @return [Array<SDL2::Display::Mode>]
986
+ *
987
+ */
988
+ static VALUE Display_modes(VALUE self)
989
+ {
990
+ int i;
991
+ int index = Display_index_int(self);
992
+ int num_modes = SDL_GetNumDisplayModes(index);
993
+ VALUE modes = rb_ary_new2(num_modes);
994
+ for (i=0; i<num_modes; ++i) {
995
+ SDL_DisplayMode mode;
996
+ HANDLE_ERROR(SDL_GetDisplayMode(index, i, &mode));
997
+ rb_ary_push(modes, DisplayMode_new(&mode));
998
+ }
999
+ return modes;
1000
+ }
1001
+
1002
+ /*
1003
+ * Get the current display mode.
1004
+ *
1005
+ * @return [SDL2::Display::Mode]
1006
+ *
1007
+ * @see #desktop_mode
1008
+ */
1009
+ static VALUE Display_current_mode(VALUE self)
1010
+ {
1011
+ SDL_DisplayMode mode;
1012
+ HANDLE_ERROR(SDL_GetCurrentDisplayMode(Display_index_int(self), &mode));
1013
+ return DisplayMode_new(&mode);
1014
+ }
1015
+
1016
+ /*
1017
+ * Get the desktop display mode.
1018
+ *
1019
+ * Normally, the return value of this method is
1020
+ * same as {#current_mode}. However,
1021
+ * when you use fullscreen and chagne the resolution,
1022
+ * this method returns the previous native display mode,
1023
+ * and not the current mode.
1024
+ *
1025
+ * @return [SDL2::Display::Mode]
1026
+ */
1027
+ static VALUE Display_desktop_mode(VALUE self)
1028
+ {
1029
+ SDL_DisplayMode mode;
1030
+ HANDLE_ERROR(SDL_GetDesktopDisplayMode(Display_index_int(self), &mode));
1031
+ return DisplayMode_new(&mode);
1032
+ }
1033
+
1034
+ /*
1035
+ * @overload closest_mode(mode)
1036
+ * Get the available display mode closest match to **mode**.
1037
+ *
1038
+ * @param mode [SDL2::Display::Mode] the desired display mode
1039
+ * @return [SDL2::Display::Mode]
1040
+ *
1041
+ */
1042
+ static VALUE Display_closest_mode(VALUE self, VALUE mode)
1043
+ {
1044
+ SDL_DisplayMode closest;
1045
+ if (!SDL_GetClosestDisplayMode(Display_index_int(self), Get_SDL_DisplayMode(mode),
1046
+ &closest))
1047
+ SDL_ERROR();
1048
+ return DisplayMode_new(&closest);
1049
+ }
1050
+
1051
+ /*
1052
+ * Get the desktop area represented by the display, with the primary
1053
+ * display located at (0, 0).
1054
+ *
1055
+ * @return [Rect]
1056
+ */
1057
+ static VALUE Display_bounds(VALUE self)
1058
+ {
1059
+ VALUE rect = rb_obj_alloc(cRect);
1060
+ HANDLE_ERROR(SDL_GetDisplayBounds(Display_index_int(self), Get_SDL_Rect(rect)));
1061
+ return rect;
1062
+ }
1063
+
1064
+ static Uint32 uint32_for_format(VALUE format)
1065
+ {
1066
+ if (rb_obj_is_kind_of(format, cPixelFormat))
1067
+ return NUM2UINT(rb_iv_get(format, "@format"));
1068
+ else
1069
+ return NUM2UINT(format);
1070
+ }
1071
+
1072
+ /*
1073
+ * Document-class: SDL2::Display::Mode
1074
+ *
1075
+ * This class represents the display mode.
1076
+ *
1077
+ * An object of this class has information about color depth, refresh rate,
1078
+ * and resolution of a display.
1079
+ *
1080
+ */
1081
+
1082
+ /*
1083
+ * @overload initialze(format, w, h, refresh_rate)
1084
+ * Create a new Display::Mode object.
1085
+ *
1086
+ * @param format [SDL2::PixelFormat, Integer] pixel format
1087
+ * @param w [Integer] the width
1088
+ * @param h [Integer] the height
1089
+ * @param refresh_rate [Integer] refresh rate
1090
+ */
1091
+ static VALUE DisplayMode_initialize(VALUE self, VALUE format, VALUE w, VALUE h,
1092
+ VALUE refresh_rate)
1093
+ {
1094
+ SDL_DisplayMode* mode = Get_SDL_DisplayMode(self);
1095
+ mode->format = uint32_for_format(format);
1096
+ mode->w = NUM2INT(w); mode->h = NUM2INT(h);
1097
+ mode->refresh_rate = NUM2INT(refresh_rate);
1098
+ return Qnil;
1099
+ }
1100
+
1101
+ /* @return [String] inspection string */
1102
+ static VALUE DisplayMode_inspect(VALUE self)
1103
+ {
1104
+ SDL_DisplayMode* mode = Get_SDL_DisplayMode(self);
1105
+ return rb_sprintf("<%s: format=%s w=%d h=%d refresh_rate=%d>",
1106
+ rb_obj_classname(self), SDL_GetPixelFormatName(mode->format),
1107
+ mode->w, mode->h, mode->refresh_rate);
1108
+
1109
+ }
1110
+
1111
+ /* @return [SDL2::PixelFormat] the pixel format of the display mode */
1112
+ static VALUE DisplayMode_format(VALUE self)
1113
+ {
1114
+ return PixelFormat_new(Get_SDL_DisplayMode(self)->format);
1115
+ }
1116
+
1117
+ /* @return [Integer] the width of the screen of the display mode */
1118
+ static VALUE DisplayMode_w(VALUE self)
1119
+ {
1120
+ return INT2NUM(Get_SDL_DisplayMode(self)->w);
1121
+ }
1122
+
1123
+ /* @return [Integer] the height of the screen of the display mode */
1124
+ static VALUE DisplayMode_h(VALUE self)
1125
+ {
1126
+ return INT2NUM(Get_SDL_DisplayMode(self)->h);
1127
+ }
1128
+
1129
+ /* @return [Integer] the refresh rate of the display mode */
1130
+ static VALUE DisplayMode_refresh_rate(VALUE self)
1131
+ {
1132
+ return INT2NUM(Get_SDL_DisplayMode(self)->refresh_rate);
1133
+ }
1134
+
1135
+ /*
1136
+ * Document-class: SDL2::Renderer
1137
+ *
1138
+ * This class represents a 2D rendering context for a window.
1139
+ *
1140
+ * You can create a renderer using {SDL2::Window#create_renderer} and
1141
+ * use it to draw figures on the window.
1142
+ *
1143
+ * # Flags
1144
+ * You can specify the OR'd bits of the following constants
1145
+ * {SDL2::Window#create_renderer when you create a new renderer}.
1146
+ *
1147
+ * * SDL2::Renderer::SOFTWARE - the renderer is a software fallback
1148
+ * * SDL2::Renderer::ACCELERATED - the renderer uses hardware acceleration
1149
+ * * SDL2::Renderer::PRESENTVSYNC - present is synchronized with the refresh rate
1150
+ * * SDL2::Renderer::TARGETTEXTURE - the renderer supports rendering to texture
1151
+ *
1152
+ * No flags(==0) gives priority to available ACCELERATED renderers
1153
+ *
1154
+ * # Blending modes
1155
+ * You can use 4 types of blending mode for rendering graphics
1156
+ * using Renderer class.
1157
+ *
1158
+ * You can change the blending mode using
1159
+ * {#draw_blend_mode=} and {SDL2::Texture#blend_mode=}.
1160
+ *
1161
+ * In the backend of SDL, opengl or direct3d blending
1162
+ * mechanism is used for blending operations.
1163
+ *
1164
+ * * SDL2::BLENDMODE_NONE - no blending (dstRGBA = srcRGBA)
1165
+ * * SDL2::BLENDMODE_BLEND - alpha blending
1166
+ * (dstRGB = (srcRGB * srcA) + (dstRGB * (1-srcA)),
1167
+ * dstA = srcA + (dstA * (1-srcA)))
1168
+ * * SDL2::BLENDMODE_ADD - additive blending
1169
+ * (dstRGB = (srcRGB * srcA) + dstRGB,
1170
+ * dstA = dstA)
1171
+ * * SDL2::BLENDMODE_MUL - color modulate
1172
+ * (dstRGB = srcRGB * dstRGB,
1173
+ * dstA = dstA)
1174
+ *
1175
+ * @!method destroy?
1176
+ * Return true if the renderer is {#destroy destroyed}.
1177
+ *
1178
+ */
1179
+
1180
+
1181
+ /*
1182
+ * @overload drivers_info
1183
+ * Return information of all available rendering contexts.
1184
+ * @return [Array<SDL2::Renderer::Info>] information about rendering contexts
1185
+ *
1186
+ */
1187
+ static VALUE Renderer_s_drivers_info(VALUE self)
1188
+ {
1189
+ int num_drivers = SDL_GetNumRenderDrivers();
1190
+ VALUE info_ary = rb_ary_new();
1191
+ int i;
1192
+ for (i=0; i<num_drivers; ++i) {
1193
+ SDL_RendererInfo info;
1194
+ HANDLE_ERROR(SDL_GetRenderDriverInfo(i, &info));
1195
+ rb_ary_push(info_ary, RendererInfo_new(&info));
1196
+ }
1197
+ return info_ary;
1198
+ }
1199
+
1200
+ /*
1201
+ * Destroy the rendering context and free associated textures.
1202
+ *
1203
+ * @return [nil]
1204
+ * @see #destroy?
1205
+ */
1206
+ static VALUE Renderer_destroy(VALUE self)
1207
+ {
1208
+ Renderer_destroy_internal(Get_Renderer(self));
1209
+ return Qnil;
1210
+ }
1211
+
1212
+ /*
1213
+ * @overload create_texture(format, access, w, h)
1214
+ * Create a new texture for the rendering context.
1215
+ *
1216
+ * You can use the following constants to specify access pattern
1217
+ *
1218
+ * * SDL2::Texture::ACCESS_STATIC - changes rarely, not lockable
1219
+ * * SDL2::Texture::ACCESS_STREAMING - changes frequently, lockable
1220
+ * * SDL2::Texture::ACCESS_TARGET - can be used as a render target
1221
+ *
1222
+ * @param [SDL2::PixelFormat,Integer] format format of the texture
1223
+ * @param [Integer] access texture access pattern
1224
+ * @param [Integer] w the width ofthe texture in pixels
1225
+ * @param [Integer] h the height ofthe texture in pixels
1226
+ *
1227
+ * @return [SDL2::Texture] the created texture
1228
+ *
1229
+ * @raise [SDL2::Error] raised when the texture cannot be created
1230
+ *
1231
+ * @see #create_texture_from
1232
+ */
1233
+ static VALUE Renderer_create_texture(VALUE self, VALUE format, VALUE access,
1234
+ VALUE w, VALUE h)
1235
+ {
1236
+ SDL_Texture* texture = SDL_CreateTexture(Get_SDL_Renderer(self),
1237
+ uint32_for_format(format),
1238
+ NUM2INT(access), NUM2INT(w), NUM2INT(h));
1239
+ if (!texture)
1240
+ SDL_ERROR();
1241
+ return Texture_new(texture, Get_Renderer(self));
1242
+ }
1243
+
1244
+ /*
1245
+ * @overload create_texture_from(surface)
1246
+ * Create a texture from an existing surface.
1247
+ *
1248
+ * @param [SDL2::Surface] surface the surface containing pixels for the texture
1249
+ * @return [SDL2::Texture] the created texture
1250
+ *
1251
+ * @raise [SDL2::Error] raised when the texture cannot be created
1252
+ *
1253
+ * @see #create_texture
1254
+ */
1255
+ static VALUE Renderer_create_texture_from(VALUE self, VALUE surface)
1256
+ {
1257
+ SDL_Texture* texture = SDL_CreateTextureFromSurface(Get_SDL_Renderer(self),
1258
+ Get_SDL_Surface(surface));
1259
+ if (texture == NULL)
1260
+ SDL_ERROR();
1261
+
1262
+ return Texture_new(texture, Get_Renderer(self));
1263
+ }
1264
+
1265
+ static SDL_Rect* Get_SDL_Rect_or_NULL(VALUE rect)
1266
+ {
1267
+ return rect == Qnil ? NULL : Get_SDL_Rect(rect);
1268
+ }
1269
+
1270
+ static SDL_Point* Get_SDL_Point_or_NULL(VALUE point)
1271
+ {
1272
+ return point == Qnil ? NULL : Get_SDL_Point(point);
1273
+ }
1274
+
1275
+ /*
1276
+ * @overload copy(texture, srcrect, dstrect)
1277
+ * Copy a portion of the texture to the current rendering target.
1278
+ *
1279
+ * @param [SDL2::Texture] texture the source texture
1280
+ * @param [SDL2::Rect,nil] srcrect the source rectangle, or nil for the entire texture
1281
+ * @param [SDL2::Rect,nil] dstrect the destination rectangle, or nil for the entire
1282
+ * rendering target; the texture will be stretched to fill the given rectangle
1283
+ *
1284
+ * @return [void]
1285
+ *
1286
+ * @see #copy_ex
1287
+ */
1288
+ static VALUE Renderer_copy(VALUE self, VALUE texture, VALUE srcrect, VALUE dstrect)
1289
+ {
1290
+ HANDLE_ERROR(SDL_RenderCopy(Get_SDL_Renderer(self),
1291
+ Get_SDL_Texture(texture),
1292
+ Get_SDL_Rect_or_NULL(srcrect),
1293
+ Get_SDL_Rect_or_NULL(dstrect)));
1294
+ return Qnil;
1295
+ }
1296
+
1297
+ /*
1298
+ * @overload copy_ex(texture, srcrect, dstrect, angle, center, flip)
1299
+ * Copy a portion of the texture to the current rendering target,
1300
+ * rotating it by angle around the given center and also flipping
1301
+ * it top-bottom and/or left-right.
1302
+ *
1303
+ * You can use the following constants to specify the horizontal/vertical flip:
1304
+ *
1305
+ * * SDL2::Renderer::FLIP_HORIZONTAL - flip horizontally
1306
+ * * SDL2::Renderer::FLIP_VERTICAL - flip vertically
1307
+ * * SDL2::Renderer::FLIP_NONE - do not flip, equal to zero
1308
+ *
1309
+ *
1310
+ * @param [SDL2::Texture] texture the source texture
1311
+ * @param [SDL2::Rect,nil] srcrect the source rectangle, or nil for the entire texture
1312
+ * @param [SDL2::Rect,nil] dstrect the destination rectangle, or nil for the entire
1313
+ * rendering target; the texture will be stretched to fill the given rectangle
1314
+ * @param [Float] angle an angle in degree indicating the rotation
1315
+ * that will be applied to dstrect
1316
+ * @param [SDL2::Point,nil] center the point around which dstrect will be rotated,
1317
+ * (if nil, rotation will be done around the center of dstrect)
1318
+ * @param [Integer] flip bits OR'd of the flip consntants
1319
+ *
1320
+ * @return [void]
1321
+ *
1322
+ * @see #copy
1323
+ */
1324
+ static VALUE Renderer_copy_ex(VALUE self, VALUE texture, VALUE srcrect, VALUE dstrect,
1325
+ VALUE angle, VALUE center, VALUE flip)
1326
+ {
1327
+ HANDLE_ERROR(SDL_RenderCopyEx(Get_SDL_Renderer(self),
1328
+ Get_SDL_Texture(texture),
1329
+ Get_SDL_Rect_or_NULL(srcrect),
1330
+ Get_SDL_Rect_or_NULL(dstrect),
1331
+ NUM2DBL(angle),
1332
+ Get_SDL_Point_or_NULL(center),
1333
+ NUM2INT(flip)));
1334
+ return Qnil;
1335
+ }
1336
+
1337
+ /*
1338
+ * Update the screen with rendering performed
1339
+ * @return [nil]
1340
+ */
1341
+ static VALUE Renderer_present(VALUE self)
1342
+ {
1343
+ SDL_RenderPresent(Get_SDL_Renderer(self));
1344
+ return Qnil;
1345
+ }
1346
+
1347
+ /*
1348
+ * Crear the rendering target with the drawing color.
1349
+ * @return [nil]
1350
+ *
1351
+ * @see #draw_color=
1352
+ */
1353
+ static VALUE Renderer_clear(VALUE self)
1354
+ {
1355
+ HANDLE_ERROR(SDL_RenderClear(Get_SDL_Renderer(self)));
1356
+ return Qnil;
1357
+ }
1358
+
1359
+ /*
1360
+ * Get the color used for drawing operations
1361
+ * @return [[Integer,Integer,Integer,Integer]]
1362
+ * red, green, blue, and alpha components of the drawing color
1363
+ * (all components are more than or equal to 0 and less than and equal to 255)
1364
+ *
1365
+ * @see #draw_color=
1366
+ */
1367
+ static VALUE Renderer_draw_color(VALUE self)
1368
+ {
1369
+ Uint8 r, g, b, a;
1370
+ HANDLE_ERROR(SDL_GetRenderDrawColor(Get_SDL_Renderer(self), &r, &g, &b, &a));
1371
+ return rb_ary_new3(4, INT2FIX(r), INT2FIX(g), INT2FIX(b), INT2FIX(a));
1372
+ }
1373
+
1374
+ /*
1375
+ * @overload draw_color=(color)
1376
+ * Set the color used for drawing operations
1377
+ *
1378
+ * All color components (including alpha) must be more than or equal to 0
1379
+ * and less than and equal to 255
1380
+ *
1381
+ * This method effects the following methods.
1382
+ *
1383
+ * * {#draw_line}
1384
+ * * {#draw_point}
1385
+ * * {#draw_rect}
1386
+ * * {#fill_rect}
1387
+ * * {#clear}
1388
+ *
1389
+ * @param [[Integer, Integer, Integer]] color
1390
+ * red, green, and blue components used for drawing
1391
+ * @param [[Integer, Integer, Integer, Integer]] color
1392
+ * red, green, blue, and alpha components used for drawing
1393
+ *
1394
+ * @return [color]
1395
+ *
1396
+ * @see #draw_color
1397
+ */
1398
+ static VALUE Renderer_set_draw_color(VALUE self, VALUE rgba)
1399
+ {
1400
+ SDL_Color color = Array_to_SDL_Color(rgba);
1401
+
1402
+ HANDLE_ERROR(SDL_SetRenderDrawColor(Get_SDL_Renderer(self),
1403
+ color.r, color.g, color.b, color.a));
1404
+
1405
+ return rgba;
1406
+ }
1407
+
1408
+ /*
1409
+ * @overload draw_line(x1, y1, x2, y2)
1410
+ * Draw a line from (x1, y1) to (x2, y2) using drawing color given by
1411
+ * {#draw_color=}.
1412
+ *
1413
+ * @param [Integer] x1 the x coordinate of the start point
1414
+ * @param [Integer] y1 the y coordinate of the start point
1415
+ * @param [Integer] x2 the x coordinate of the end point
1416
+ * @param [Integer] y2 the y coordinate of the end point
1417
+ * @return [nil]
1418
+ */
1419
+ static VALUE Renderer_draw_line(VALUE self, VALUE x1, VALUE y1, VALUE x2, VALUE y2)
1420
+ {
1421
+ HANDLE_ERROR(SDL_RenderDrawLine(Get_SDL_Renderer(self),
1422
+ NUM2INT(x1), NUM2INT(y1), NUM2INT(x2), NUM2INT(y2)));
1423
+ return Qnil;
1424
+ }
1425
+
1426
+ /*
1427
+ * @overload draw_point(x, y)
1428
+ * Draw a point at (x, y) using drawing color given by {#draw_color=}.
1429
+ *
1430
+ * @param [Integer] x the x coordinate of the point
1431
+ * @param [Integer] y the y coordinate of the point
1432
+ *
1433
+ * @return [nil]
1434
+ */
1435
+ static VALUE Renderer_draw_point(VALUE self, VALUE x, VALUE y)
1436
+ {
1437
+ HANDLE_ERROR(SDL_RenderDrawPoint(Get_SDL_Renderer(self), NUM2INT(x), NUM2INT(y)));
1438
+ return Qnil;
1439
+ }
1440
+
1441
+ /*
1442
+ * @overload draw_rect(rect)
1443
+ * Draw a rectangle using drawing color given by {#draw_color=}.
1444
+ *
1445
+ * @param [SDL2::Rect] rect the drawing rectangle
1446
+ *
1447
+ * @return [nil]
1448
+ */
1449
+ static VALUE Renderer_draw_rect(VALUE self, VALUE rect)
1450
+ {
1451
+ HANDLE_ERROR(SDL_RenderDrawRect(Get_SDL_Renderer(self), Get_SDL_Rect(rect)));
1452
+ return Qnil;
1453
+ }
1454
+
1455
+ /*
1456
+ * @overload fill_rect(rect)
1457
+ * Draw a filled rectangle using drawing color given by {#draw_color=}.
1458
+ *
1459
+ * @param [SDL2::Rect] rect the drawing rectangle
1460
+ *
1461
+ * @return [nil]
1462
+ */
1463
+ static VALUE Renderer_fill_rect(VALUE self, VALUE rect)
1464
+ {
1465
+ HANDLE_ERROR(SDL_RenderFillRect(Get_SDL_Renderer(self), Get_SDL_Rect(rect)));
1466
+ return Qnil;
1467
+ }
1468
+
1469
+ /*
1470
+ * Get information about _self_ rendering context .
1471
+ *
1472
+ * @return [SDL2::Renderer::Info] rendering information
1473
+ */
1474
+ static VALUE Renderer_info(VALUE self)
1475
+ {
1476
+ SDL_RendererInfo info;
1477
+ HANDLE_ERROR(SDL_GetRendererInfo(Get_SDL_Renderer(self), &info));
1478
+ return RendererInfo_new(&info);
1479
+ }
1480
+
1481
+ /*
1482
+ * Get the blend mode used for drawing operations like
1483
+ * {#fill_rect} and {#draw_line}.
1484
+ *
1485
+ * For the blending modes, see [blending modes](#label-Blending+modes)
1486
+ *
1487
+ * @return [Integer]
1488
+ *
1489
+ * @see #draw_blend_mode=
1490
+ */
1491
+ static VALUE Renderer_draw_blend_mode(VALUE self)
1492
+ {
1493
+ SDL_BlendMode mode;
1494
+ HANDLE_ERROR(SDL_GetRenderDrawBlendMode(Get_SDL_Renderer(self), &mode));
1495
+ return INT2FIX(mode);
1496
+ }
1497
+
1498
+ /*
1499
+ * @overload draw_blend_mode=(mode)
1500
+ * Set the blend mode used for drawing operations.
1501
+ *
1502
+ * This method effects the following methods.
1503
+ *
1504
+ * * {#draw_line}
1505
+ * * {#draw_point}
1506
+ * * {#draw_rect}
1507
+ * * {#fill_rect}
1508
+ * * {#clear}
1509
+ *
1510
+ * @param mode [Integer] the blending mode
1511
+ * @return mode
1512
+ *
1513
+ * @see #draw_blend_mode
1514
+ *
1515
+ */
1516
+ static VALUE Renderer_set_draw_blend_mode(VALUE self, VALUE mode)
1517
+ {
1518
+ HANDLE_ERROR(SDL_SetRenderDrawBlendMode(Get_SDL_Renderer(self), NUM2INT(mode)));
1519
+ return mode;
1520
+ }
1521
+
1522
+ /*
1523
+ * Get the clip rectangle for the current target.
1524
+ *
1525
+ * @return [SDL2::Rect] the current clip rectangle
1526
+ *
1527
+ */
1528
+ static VALUE Renderer_clip_rect(VALUE self)
1529
+ {
1530
+ VALUE rect = rb_obj_alloc(cRect);
1531
+ SDL_RenderGetClipRect(Get_SDL_Renderer(self), Get_SDL_Rect(rect));
1532
+ return rect;
1533
+ }
1534
+
1535
+ #if SDL_VERSION_ATLEAST(2,0,4)
1536
+ static VALUE Render_clip_enabled_p(VALUE self)
1537
+ {
1538
+ return INT2BOOL(SDL_RenderIsClipEnabled(Get_SDL_Renderer(self)));
1539
+ }
1540
+ #endif
1541
+
1542
+ static VALUE Renderer_logical_size(VALUE self)
1543
+ {
1544
+ int w, h;
1545
+ SDL_RenderGetLogicalSize(Get_SDL_Renderer(self), &w, &h);
1546
+ return rb_ary_new3(2, INT2FIX(w), INT2FIX(h));
1547
+ }
1548
+
1549
+ static VALUE Renderer_scale(VALUE self)
1550
+ {
1551
+ float scaleX, scaleY;
1552
+ SDL_RenderGetScale(Get_SDL_Renderer(self), &scaleX, &scaleY);
1553
+ return rb_ary_new3(2, DBL2NUM(scaleX), DBL2NUM(scaleY));
1554
+ }
1555
+
1556
+ static VALUE Renderer_viewport(VALUE self)
1557
+ {
1558
+ VALUE rect = rb_obj_alloc(cRect);
1559
+ SDL_RenderGetViewport(Get_SDL_Renderer(self), Get_SDL_Rect(rect));
1560
+ return rect;
1561
+ }
1562
+
1563
+ /*
1564
+ * Return true if the renderer supports render target.
1565
+ *
1566
+ * @see #render_target=
1567
+ */
1568
+ static VALUE Renderer_support_render_target_p(VALUE self)
1569
+ {
1570
+ return INT2BOOL(SDL_RenderTargetSupported(Get_SDL_Renderer(self)));
1571
+ }
1572
+
1573
+ static VALUE Renderer_output_size(VALUE self)
1574
+ {
1575
+ int w, h;
1576
+ HANDLE_ERROR(SDL_GetRendererOutputSize(Get_SDL_Renderer(self), &w, &h));
1577
+ return rb_ary_new3(2, INT2FIX(w), INT2FIX(h));
1578
+ }
1579
+
1580
+ /*
1581
+ * @overload render_target=(target)
1582
+ * Set a texture as the current render target.
1583
+ *
1584
+ * Some renderers have ability to render to a texture instead of a screen.
1585
+ * You can judge whether your renderer has this ability using
1586
+ * {#support_render_target?}.
1587
+ *
1588
+ * The target texture musbe be {#create_texture created} with the
1589
+ * SDL2::Texture::ACCESS_TARGET flag.
1590
+ *
1591
+ * @param [SDL2::Texture,nil] target the targeted texture, or nil
1592
+ * for the default render target(i.e. screen)
1593
+ *
1594
+ * @return [target]
1595
+ *
1596
+ * @see #render_target
1597
+ */
1598
+ static VALUE Renderer_set_render_target(VALUE self, VALUE target)
1599
+ {
1600
+ HANDLE_ERROR(SDL_SetRenderTarget(Get_SDL_Renderer(self),
1601
+ (target == Qnil) ? NULL : Get_SDL_Texture(target)));
1602
+ rb_iv_set(self, "render_target", target);
1603
+ return target;
1604
+ }
1605
+
1606
+ /*
1607
+ * Get the current render target.
1608
+ *
1609
+ * @return [SDL2::Texture] the current rendering target
1610
+ * @return [nil] for the default render target (i.e. screen)
1611
+ *
1612
+ * @see #render_target=
1613
+ * @see #support_render_target?
1614
+ */
1615
+ static VALUE Renderer_render_target(VALUE self)
1616
+ {
1617
+ return rb_iv_get(self, "render_target");
1618
+ }
1619
+
1620
+ /*
1621
+ * Reset the render target to the screen.
1622
+ *
1623
+ * @return [nil]
1624
+ */
1625
+ static VALUE Renderer_reset_render_target(VALUE self)
1626
+ {
1627
+ return Renderer_set_render_target(self, Qnil);
1628
+ }
1629
+
1630
+ /* @return [Hash<String=>Object>] (GC) debug information */
1631
+ static VALUE Renderer_debug_info(VALUE self)
1632
+ {
1633
+ Renderer* r = Get_Renderer(self);
1634
+ VALUE info = rb_hash_new();
1635
+ int num_active_textures = 0;
1636
+ int i;
1637
+ rb_hash_aset(info, rb_str_new2("destroy?"), INT2BOOL(r->renderer == NULL));
1638
+ rb_hash_aset(info, rb_str_new2("max_textures"), INT2NUM(r->max_textures));
1639
+ rb_hash_aset(info, rb_str_new2("num_textures"), INT2NUM(r->num_textures));
1640
+ for (i=0; i<r->num_textures; ++i)
1641
+ if (r->textures[i]->texture)
1642
+ ++num_active_textures;
1643
+ rb_hash_aset(info, rb_str_new2("num_active_textures"), INT2NUM(num_active_textures));
1644
+ rb_hash_aset(info, rb_str_new2("refcount"), INT2NUM(r->refcount));
1645
+
1646
+ return info;
1647
+ }
1648
+
1649
+ /*
1650
+ * Document-class: SDL2::Texture
1651
+ *
1652
+ * This class represents the texture associated with a renderer.
1653
+ *
1654
+ *
1655
+ * @!method destroy?
1656
+ * Return true if the texture is {#destroy destroyed}.
1657
+ */
1658
+
1659
+ /*
1660
+ * Destroy the texture and deallocate memory.
1661
+ *
1662
+ * @see #destroy?
1663
+ */
1664
+ static VALUE Texture_destroy(VALUE self)
1665
+ {
1666
+ Texture_destroy_internal(Get_Texture(self));
1667
+ return Qnil;
1668
+ }
1669
+
1670
+ /*
1671
+ * Get the blending mode of the texture.
1672
+ *
1673
+ * @return [Integer] blend mode
1674
+ *
1675
+ * @see #blend_mode=
1676
+ */
1677
+ static VALUE Texture_blend_mode(VALUE self)
1678
+ {
1679
+ SDL_BlendMode mode;
1680
+ HANDLE_ERROR(SDL_GetTextureBlendMode(Get_SDL_Texture(self), &mode));
1681
+ return INT2FIX(mode);
1682
+ }
1683
+
1684
+ /*
1685
+ * @overload blend_mode=(mode)
1686
+ * Set the blending model of the texture.
1687
+ *
1688
+ * @param mode [Integer] blending mode
1689
+ * @return [mode]
1690
+ *
1691
+ * @see #blend_mode
1692
+ */
1693
+ static VALUE Texture_set_blend_mode(VALUE self, VALUE mode)
1694
+ {
1695
+ HANDLE_ERROR(SDL_SetTextureBlendMode(Get_SDL_Texture(self), NUM2INT(mode)));
1696
+ return mode;
1697
+ }
1698
+
1699
+ /*
1700
+ * Get an additional alpha value used in render copy operations.
1701
+ *
1702
+ * @return [Integer] the current alpha value
1703
+ *
1704
+ * @see #alpha_mod=
1705
+ */
1706
+ static VALUE Texture_alpha_mod(VALUE self)
1707
+ {
1708
+ Uint8 alpha;
1709
+ HANDLE_ERROR(SDL_GetTextureAlphaMod(Get_SDL_Texture(self), &alpha));
1710
+ return INT2FIX(alpha);
1711
+ }
1712
+
1713
+ /*
1714
+ * @overload alpha_mod=(alpha)
1715
+ * Set an additional alpha value used in render copy operations.
1716
+ *
1717
+ * @param alpha [Integer] the alpha value multiplied into copy operation,
1718
+ * from 0 to 255
1719
+ * @return [alpha]
1720
+ *
1721
+ * @see #alpha_mod
1722
+ */
1723
+ static VALUE Texture_set_alpha_mod(VALUE self, VALUE alpha)
1724
+ {
1725
+ HANDLE_ERROR(SDL_SetTextureAlphaMod(Get_SDL_Texture(self), NUM2UCHAR(alpha)));
1726
+ return alpha;
1727
+ }
1728
+
1729
+ /*
1730
+ * Get an additional color value used in render copy operations.
1731
+ *
1732
+ * @return [[Integer, Integer, Integer]] the current red, green, and blue
1733
+ * color value.
1734
+ */
1735
+ static VALUE Texture_color_mod(VALUE self)
1736
+ {
1737
+ Uint8 r, g, b;
1738
+ HANDLE_ERROR(SDL_GetTextureColorMod(Get_SDL_Texture(self), &r, &g, &b));
1739
+ return rb_ary_new3(3, INT2FIX(r), INT2FIX(g), INT2FIX(b));
1740
+ }
1741
+
1742
+ /*
1743
+ * @overload color_mod=(rgb)
1744
+ * Set an additional color value used in render copy operations.
1745
+ *
1746
+ * @param rgb [[Integer, Integer, Integer]] the red, green, and blue
1747
+ * color value multiplied into copy operations.
1748
+ * @return [rgb]
1749
+ */
1750
+ static VALUE Texture_set_color_mod(VALUE self, VALUE rgb)
1751
+ {
1752
+ SDL_Color color = Array_to_SDL_Color(rgb);
1753
+ HANDLE_ERROR(SDL_SetTextureColorMod(Get_SDL_Texture(self),
1754
+ color.r, color.g, color.b));
1755
+ return rgb;
1756
+ }
1757
+
1758
+ /*
1759
+ * Get the format of the texture.
1760
+ *
1761
+ * @return [SDL2::PixelFormat]
1762
+ */
1763
+ static VALUE Texture_format(VALUE self)
1764
+ {
1765
+ Uint32 format;
1766
+ HANDLE_ERROR(SDL_QueryTexture(Get_SDL_Texture(self), &format, NULL, NULL, NULL));
1767
+ return PixelFormat_new(format);
1768
+ }
1769
+
1770
+ /*
1771
+ * Get the access pattern allowed for the texture.
1772
+ *
1773
+ * The return value is one of the following:
1774
+ *
1775
+ * * SDL2::Texture::ACCESS_STATIC - changes rarely, not lockable
1776
+ * * SDL2::Texture::ACCESS_STREAMING - changes frequently, lockable
1777
+ * * SDL2::Texture::ACCESS_TARGET - can be used as a render target
1778
+ *
1779
+ * @return [Integer]
1780
+ *
1781
+ * @see SDL2::Renderer#create_texture
1782
+ */
1783
+ static VALUE Texture_access_pattern(VALUE self)
1784
+ {
1785
+ int access;
1786
+ HANDLE_ERROR(SDL_QueryTexture(Get_SDL_Texture(self), NULL, &access, NULL, NULL));
1787
+ return INT2FIX(access);
1788
+ }
1789
+
1790
+ /*
1791
+ * Get the width of the texture.
1792
+ *
1793
+ * @return [Integer]
1794
+ *
1795
+ * @see SDL2::Renderer#create_texture
1796
+ */
1797
+ static VALUE Texture_w(VALUE self)
1798
+ {
1799
+ int w;
1800
+ HANDLE_ERROR(SDL_QueryTexture(Get_SDL_Texture(self), NULL, NULL, &w, NULL));
1801
+ return INT2FIX(w);
1802
+ }
1803
+
1804
+ /*
1805
+ * Get the height of the texture.
1806
+ *
1807
+ * @return [Integer]
1808
+ *
1809
+ * @see SDL2::Renderer#create_texture
1810
+ */
1811
+ static VALUE Texture_h(VALUE self)
1812
+ {
1813
+ int h;
1814
+ HANDLE_ERROR(SDL_QueryTexture(Get_SDL_Texture(self), NULL, NULL, NULL, &h));
1815
+ return INT2FIX(h);
1816
+ }
1817
+
1818
+ /* @return [String] inspection string */
1819
+ static VALUE Texture_inspect(VALUE self)
1820
+ {
1821
+ Texture* t = Get_Texture(self);
1822
+ Uint32 format;
1823
+ int access, w, h;
1824
+ if (!t->texture)
1825
+ return rb_sprintf("<%s: (destroyed)>", rb_obj_classname(self));
1826
+
1827
+ HANDLE_ERROR(SDL_QueryTexture(t->texture, &format, &access, &w, &h));
1828
+ return rb_sprintf("<%s:%p format=%s access=%d w=%d h=%d>",
1829
+ rb_obj_classname(self), (void*)self, SDL_GetPixelFormatName(format),
1830
+ access, w, h);
1831
+ }
1832
+
1833
+ /* @return [Hash<String=>Object>] (GC) debugging information */
1834
+ static VALUE Texture_debug_info(VALUE self)
1835
+ {
1836
+ Texture* t = Get_Texture(self);
1837
+ VALUE info = rb_hash_new();
1838
+ rb_hash_aset(info, rb_str_new2("destroy?"), INT2BOOL(t->texture == NULL));
1839
+ rb_hash_aset(info, rb_str_new2("refcount"), INT2NUM(t->refcount));
1840
+ return info;
1841
+ }
1842
+
1843
+ /*
1844
+ * Document-class: SDL2::Surface
1845
+ *
1846
+ * This class represents bitmap images (collection of pixels).
1847
+ *
1848
+ * Normally in SDL2, this class is not used for drawing a image
1849
+ * on a window. {SDL2::Texture} is used for the purpose.
1850
+ *
1851
+ * Mainly this class is for compatibility with SDL1, but the class
1852
+ * is useful for simple pixel manipulation.
1853
+ * For example, {SDL2::TTF} can create only surfaces, not textures.
1854
+ * You can convert a surface to texture with
1855
+ * {SDL2::Renderer#create_texture_from}.
1856
+ *
1857
+ * @!method destroy?
1858
+ * Return true if the surface is {#destroy destroyed}.
1859
+ *
1860
+ */
1861
+
1862
+ /*
1863
+ * @overload load_bmp(path)
1864
+ * Load a surface from bmp file.
1865
+ *
1866
+ * @param path [String] bmp file path
1867
+ * @return [SDL2::Surface]
1868
+ * @raise [SDL2::Error] raised when an error occurs.
1869
+ * For example, if there is no file or the file file
1870
+ * format is not Windows BMP.
1871
+ *
1872
+ */
1873
+ static VALUE Surface_s_load_bmp(VALUE self, VALUE fname)
1874
+ {
1875
+ SDL_Surface* surface = SDL_LoadBMP(StringValueCStr(fname));
1876
+
1877
+ if (surface == NULL)
1878
+ HANDLE_ERROR(-1);
1879
+
1880
+ return Surface_new(surface);
1881
+ }
1882
+
1883
+ /*
1884
+ * @overload from_string(string, width, heigth, depth, pitch=nil, rmask=nil, gmask=nil, bmask=nil, amask=nil)
1885
+ *
1886
+ * Create a RGB surface from pixel data as String object.
1887
+ *
1888
+ * If rmask, gmask, bmask are omitted, the default masks are used.
1889
+ * If amask is omitted, alpha mask is considered to be zero.
1890
+ *
1891
+ * @param string [String] the pixel data
1892
+ * @param width [Integer] the width of the creating surface
1893
+ * @param height [Integer] the height of the creating surface
1894
+ * @param depth [Integer] the color depth (in bits) of the creating surface
1895
+ * @param pitch [Integer] the number of bytes of one scanline
1896
+ * if this argument is omitted, width*depth/8 is used.
1897
+ * @param rmask [Integer] the red mask of a pixel
1898
+ * @param gmask [Integer] the green mask of a pixel
1899
+ * @param bmask [Integer] the blue mask of a pixel
1900
+ * @param amask [Integer] the alpha mask of a pixel
1901
+ * @return [SDL2::Surface] a new surface
1902
+ * @raise [SDL2::Error] raised when an error occurs in C SDL library
1903
+ *
1904
+ */
1905
+ static VALUE Surface_s_from_string(int argc, VALUE* argv, VALUE self)
1906
+ {
1907
+ VALUE string, width, height, depth, pitch, Rmask, Gmask, Bmask, Amask;
1908
+ int w, h, d, p, r, g, b, a;
1909
+ SDL_Surface* surface;
1910
+ void* pixels;
1911
+ Surface* s;
1912
+
1913
+ rb_scan_args(argc, argv, "45", &string, &width, &height, &depth,
1914
+ &pitch, &Rmask, &Gmask, &Bmask, &Amask);
1915
+ StringValue(string);
1916
+ w = NUM2INT(width);
1917
+ h = NUM2INT(height);
1918
+ d = NUM2INT(depth);
1919
+ p = (pitch == Qnil) ? d*w/8 : NUM2INT(pitch);
1920
+ r = (Rmask == Qnil) ? 0 : NUM2UINT(Rmask);
1921
+ g = (Gmask == Qnil) ? 0 : NUM2UINT(Gmask);
1922
+ b = (Bmask == Qnil) ? 0 : NUM2UINT(Bmask);
1923
+ a = (Amask == Qnil) ? 0 : NUM2UINT(Amask);
1924
+
1925
+ if (RSTRING_LEN(string) < p*h)
1926
+ rb_raise(rb_eArgError, "String too short");
1927
+ if (p < d*w/8 )
1928
+ rb_raise(rb_eArgError, "pitch too small");
1929
+
1930
+ pixels = ruby_xmalloc(RSTRING_LEN(string));
1931
+ memcpy(pixels, RSTRING_PTR(string), RSTRING_LEN(string));
1932
+ surface = SDL_CreateRGBSurfaceFrom(pixels, w, h, d, p, r, g, b, a);
1933
+ if (!surface)
1934
+ SDL_ERROR();
1935
+
1936
+ RB_GC_GUARD(string);
1937
+
1938
+ s = ALLOC(Surface);
1939
+ s->surface = surface;
1940
+ s->need_to_free_pixels = 1;
1941
+ return Data_Wrap_Struct(cSurface, 0, Surface_free, s);
1942
+ }
1943
+
1944
+ /*
1945
+ * Destroy the surface and deallocate the memory for pixels.
1946
+ *
1947
+ * @return [nil]
1948
+ * @see #destroy?
1949
+ */
1950
+ static VALUE Surface_destroy(VALUE self)
1951
+ {
1952
+ Surface* s = Get_Surface(self);
1953
+ if (s->need_to_free_pixels)
1954
+ free(s->surface->pixels);
1955
+ s->need_to_free_pixels = 0;
1956
+ if (s->surface)
1957
+ SDL_FreeSurface(s->surface);
1958
+ s->surface = NULL;
1959
+ return Qnil;
1960
+ }
1961
+
1962
+ /*
1963
+ * Get the blending mode of the surface used for blit operations.
1964
+ *
1965
+ * @return [Integer]
1966
+ * @see #blend_mode=
1967
+ */
1968
+ static VALUE Surface_blend_mode(VALUE self)
1969
+ {
1970
+ SDL_BlendMode mode;
1971
+ HANDLE_ERROR(SDL_GetSurfaceBlendMode(Get_SDL_Surface(self), &mode));
1972
+ return INT2FIX(mode);
1973
+ }
1974
+
1975
+ /*
1976
+ * @overload blend_mode=(mode)
1977
+ * Set the blending mode of the surface used for blit operations.
1978
+ *
1979
+ * @param mode [Integer] the blending mode
1980
+ * @return [mode]
1981
+ * @see #blend_mode
1982
+ */
1983
+ static VALUE Surface_set_blend_mode(VALUE self, VALUE mode)
1984
+ {
1985
+ HANDLE_ERROR(SDL_SetSurfaceBlendMode(Get_SDL_Surface(self), NUM2INT(mode)));
1986
+ return mode;
1987
+ }
1988
+
1989
+ /*
1990
+ * Return true if the surface need to lock when you get access to the
1991
+ * pixel data of the surface.
1992
+ *
1993
+ * @see #lock
1994
+ */
1995
+ static VALUE Surface_must_lock_p(VALUE self)
1996
+ {
1997
+ return INT2BOOL(SDL_MUSTLOCK(Get_SDL_Surface(self)));
1998
+ }
1999
+
2000
+ /*
2001
+ * Lock the surface.
2002
+ *
2003
+ * @return [nil]
2004
+ *
2005
+ * @see #unlock
2006
+ * @see #must_lock?
2007
+ */
2008
+ static VALUE Surface_lock(VALUE self)
2009
+ {
2010
+ HANDLE_ERROR(SDL_LockSurface(Get_SDL_Surface(self)));
2011
+ return Qnil;
2012
+ }
2013
+
2014
+ /*
2015
+ * Unlock the surface.
2016
+ *
2017
+ * @return [nil]
2018
+ *
2019
+ * @see #lock
2020
+ */
2021
+ static VALUE Surface_unlock(VALUE self)
2022
+ {
2023
+ SDL_UnlockSurface(Get_SDL_Surface(self));
2024
+ return Qnil;
2025
+ }
2026
+
2027
+ /*
2028
+ * @overload pixel(x, y)
2029
+ * Get a pixel data at (**x**, **y**)
2030
+ *
2031
+ * @param x [Integer] the x coordinate
2032
+ * @param y [Integer] the y coordinate
2033
+ * @return [Integer] pixel data
2034
+ *
2035
+ * @see #pixel_color
2036
+ *
2037
+ */
2038
+ static VALUE Surface_pixel(VALUE self, VALUE x_coord, VALUE y_coord)
2039
+ {
2040
+ int x = NUM2INT(x_coord);
2041
+ int y = NUM2INT(y_coord);
2042
+ SDL_Surface* surface = Get_SDL_Surface(self);
2043
+ int offset;
2044
+ Uint32 pixel = 0;
2045
+ int i;
2046
+
2047
+ if (x < 0 || x >= surface->w || y < 0 || y >= surface->h)
2048
+ rb_raise(rb_eArgError, "(%d, %d) out of range for %dx%d",
2049
+ x, y, surface->w, surface->h);
2050
+ offset = surface->pitch * y + surface->format->BytesPerPixel * x;
2051
+ for (i=0; i<surface->format->BytesPerPixel; ++i) {
2052
+ pixel += *((Uint8*)surface->pixels + offset + i) << (8*i);
2053
+ }
2054
+
2055
+ return UINT2NUM(SDL_SwapLE32(pixel));
2056
+ }
2057
+
2058
+ /*
2059
+ * Get all pixel data of the surface as a string.
2060
+ *
2061
+ * @return [String]
2062
+ *
2063
+ */
2064
+ static VALUE Surface_pixels(VALUE self)
2065
+ {
2066
+ SDL_Surface* surface = Get_SDL_Surface(self);
2067
+ int size = surface->h * surface->pitch;
2068
+ return rb_str_new(surface->pixels, size);
2069
+ }
2070
+
2071
+ /*
2072
+ * Get the pitch (bytes per horizontal line) of the surface.
2073
+ *
2074
+ * @return [Integer]
2075
+ */
2076
+ static VALUE Surface_pitch(VALUE self)
2077
+ {
2078
+ return UINT2NUM(Get_SDL_Surface(self)->pitch);
2079
+ }
2080
+
2081
+ /*
2082
+ * Get bits per pixel of the surface.
2083
+ *
2084
+ * @return [Integer]
2085
+ */
2086
+ static VALUE Surface_bits_per_pixel(VALUE self)
2087
+ {
2088
+ return UCHAR2NUM(Get_SDL_Surface(self)->format->BitsPerPixel);
2089
+ }
2090
+
2091
+ /*
2092
+ * Get bytes per pixel of the surface.
2093
+ *
2094
+ * @return [Integer]
2095
+ */
2096
+ static VALUE Surface_bytes_per_pixel(VALUE self)
2097
+ {
2098
+ return UCHAR2NUM(Get_SDL_Surface(self)->format->BytesPerPixel);
2099
+ }
2100
+
2101
+ /*
2102
+ * @overload pixel_color(x, y)
2103
+ * Get the pixel color (r,g,b and a) at (**x**, **y**) of the surface.
2104
+ *
2105
+ * @param x [Integer] the x coordinate
2106
+ * @param y [Integer] the y coordinate
2107
+ * @return [[Integer, Integer, Integer, Integer]]
2108
+ * the red, green, blue, and alpha component of the specified pixel.
2109
+ *
2110
+ */
2111
+ static VALUE Surface_pixel_color(VALUE self, VALUE x, VALUE y)
2112
+ {
2113
+ Uint32 pixel = NUM2UINT(Surface_pixel(self, x, y));
2114
+ SDL_Surface* surface = Get_SDL_Surface(self);
2115
+ Uint8 r, g, b, a;
2116
+ SDL_GetRGBA(pixel, surface->format, &r, &g, &b, &a);
2117
+
2118
+ return rb_ary_new3(4, UCHAR2NUM(r), UCHAR2NUM(g), UCHAR2NUM(b), UCHAR2NUM(a));
2119
+ }
2120
+
2121
+ static Uint32 pixel_value(VALUE val, SDL_PixelFormat* format)
2122
+ {
2123
+ if (RTEST(rb_funcall(val, rb_intern("integer?"), 0, 0))) {
2124
+ return NUM2UINT(val);
2125
+ } else {
2126
+ long len;
2127
+ Uint8 r, g, b, a;
2128
+ Check_Type(val, T_ARRAY);
2129
+ len = RARRAY_LEN(val);
2130
+ if (len == 3 || len == 4) {
2131
+ r = NUM2UCHAR(rb_ary_entry(val, 0));
2132
+ g = NUM2UCHAR(rb_ary_entry(val, 1));
2133
+ b = NUM2UCHAR(rb_ary_entry(val, 2));
2134
+ if (len == 3)
2135
+ a = 255;
2136
+ else
2137
+ a = NUM2UCHAR(rb_ary_entry(val, 3));
2138
+ return SDL_MapRGBA(format, r, g, b, a);
2139
+ } else {
2140
+ rb_raise(rb_eArgError, "Wrong length of array (%ld for 3..4)", len);
2141
+ }
2142
+ }
2143
+ return 0;
2144
+ }
2145
+
2146
+ /*
2147
+ * Unset the color key of the surface.
2148
+ *
2149
+ * @return [nil]
2150
+ *
2151
+ * @see #color_key=
2152
+ */
2153
+ static VALUE Surface_unset_color_key(VALUE self)
2154
+ {
2155
+ HANDLE_ERROR(SDL_SetColorKey(Get_SDL_Surface(self), SDL_FALSE, 0));
2156
+ return Qnil;
2157
+ }
2158
+
2159
+ /*
2160
+ * @overload color_key=(key)
2161
+ * Set the color key of the surface
2162
+ *
2163
+ * @param key [Integer, Array<Integer>]
2164
+ * the color key, pixel value (see {#pixel}) or pixel color (array of
2165
+ * three or four integer elements).
2166
+ *
2167
+ * @return [key]
2168
+ *
2169
+ * @see #color_key
2170
+ * @see #unset_color_key
2171
+ */
2172
+ static VALUE Surface_set_color_key(VALUE self, VALUE key)
2173
+ {
2174
+ SDL_Surface* surface = Get_SDL_Surface(self);
2175
+ if (key == Qnil)
2176
+ return Surface_unset_color_key(self);
2177
+
2178
+ HANDLE_ERROR(SDL_SetColorKey(surface, SDL_TRUE, pixel_value(key, surface->format)));
2179
+
2180
+ return key;
2181
+ }
2182
+
2183
+ /*
2184
+ * Get the color key of the surface
2185
+ *
2186
+ * @return [Integer] the color key, as pixel value (see {#pixel})
2187
+ *
2188
+ * @see #color_key=
2189
+ * @see #unset_color_key
2190
+ */
2191
+ static VALUE Surface_color_key(VALUE self)
2192
+ {
2193
+ Uint32 key;
2194
+ if (SDL_GetColorKey(Get_SDL_Surface(self), &key) < 0)
2195
+ return Qnil;
2196
+ else
2197
+ return UINT2NUM(key);
2198
+ }
2199
+
2200
+ /*
2201
+ * Get the width of the surface.
2202
+ *
2203
+ * @return [Integer]
2204
+ */
2205
+ static VALUE Surface_w(VALUE self)
2206
+ {
2207
+ return INT2NUM(Get_SDL_Surface(self)->w);
2208
+ }
2209
+
2210
+ /*
2211
+ * Get the height of the surface.
2212
+ *
2213
+ * @return [Integer]
2214
+ */
2215
+ static VALUE Surface_h(VALUE self)
2216
+ {
2217
+ return INT2NUM(Get_SDL_Surface(self)->h);
2218
+ }
2219
+
2220
+
2221
+ /*
2222
+ * @overload blit(src, srcrect, dst, dstrect)
2223
+ * Perform a fast blit from **src** surface to **dst** surface.
2224
+ *
2225
+ * @param src [SDL2::Surface] the source surface
2226
+ * @param srcrect [SDL2::Rect,nil] the region in the source surface,
2227
+ * if nil is given, the whole source is used
2228
+ * @param dst [SDL2::Surface] the destination surface
2229
+ * @param dstrect [SDL2::Rect,nil] the region in the destination surface
2230
+ * if nil is given, the source image is copied to (0, 0) on
2231
+ * the destination surface.
2232
+ * **dstrect** is changed by this method to store the
2233
+ * actually copied region (since the surface has clipping functionality,
2234
+ * actually copied region may be different from given **dstrect**).
2235
+ * @return [nil]
2236
+ */
2237
+ static VALUE Surface_s_blit(VALUE self, VALUE src, VALUE srcrect, VALUE dst, VALUE dstrect)
2238
+ {
2239
+ HANDLE_ERROR(SDL_BlitSurface(Get_SDL_Surface(src),
2240
+ Get_SDL_Rect_or_NULL(srcrect),
2241
+ Get_SDL_Surface(dst),
2242
+ Get_SDL_Rect_or_NULL(dstrect)));
2243
+ return Qnil;
2244
+ }
2245
+
2246
+ /*
2247
+ * @overload new(width, height, depth)
2248
+ * @overload new(width, height, depth, amask)
2249
+ * @overload new(width, heigth, depth, rmask, gmask, bmask, amask)
2250
+ *
2251
+ * @param width [Integer]
2252
+ * @return [SDL2::Surface]
2253
+ */
2254
+ static VALUE Surface_s_new(int argc, VALUE* argv, VALUE self)
2255
+ {
2256
+ VALUE width, height, depth;
2257
+ Uint32 Rmask, Gmask, Bmask, Amask;
2258
+ SDL_Surface * surface;
2259
+
2260
+ if (argc == 3) {
2261
+ rb_scan_args(argc, argv, "30", &width, &height, &depth);
2262
+ Rmask = Gmask = Bmask = Amask = 0;
2263
+ } else if (argc == 7) {
2264
+ VALUE rm, gm, bm, am;
2265
+ rb_scan_args(argc, argv, "70", &width, &height, &depth, &rm, &gm, &bm, &am);
2266
+ Rmask = NUM2UINT(rm); Gmask = NUM2UINT(gm);
2267
+ Bmask = NUM2UINT(bm); Amask = NUM2UINT(am);
2268
+ } else {
2269
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 4 or 7)", argc);
2270
+ }
2271
+
2272
+ surface = SDL_CreateRGBSurface(0, NUM2INT(width), NUM2INT(height), NUM2INT(depth),
2273
+ Rmask, Gmask, Bmask, Amask);
2274
+ if (!surface)
2275
+ SDL_ERROR();
2276
+
2277
+ return Surface_new(surface);
2278
+ }
2279
+
2280
+ #define FIELD_ACCESSOR(classname, typename, field) \
2281
+ static VALUE classname##_##field(VALUE self) \
2282
+ { \
2283
+ typename* r; Data_Get_Struct(self, typename, r); \
2284
+ return INT2NUM(r->field); \
2285
+ } \
2286
+ static VALUE classname##_set_##field(VALUE self, VALUE val) \
2287
+ { \
2288
+ typename* r; Data_Get_Struct(self, typename, r); \
2289
+ r->field = NUM2INT(val); return val; \
2290
+ }
2291
+
2292
+
2293
+ /* Document-class: SDL2::Rect
2294
+ *
2295
+ * This class represents a rectangle in SDL2.
2296
+ *
2297
+ * Any rectanle is represented by four attributes x, y, w, and h,
2298
+ * and these four attributes must be integer.
2299
+ *
2300
+ * @!attribute [rw] x
2301
+ * X coordiante of the left-top point of the rectangle
2302
+ * @return [Integer]
2303
+ *
2304
+ * @!attribute [rw] y
2305
+ * Y coordiante of the left-top point of the rectangle
2306
+ * @return [Integer]
2307
+ *
2308
+ * @!attribute [rw] w
2309
+ * Width of the rectangle
2310
+ * @return [Integer]
2311
+ *
2312
+ * @!attribute [rw] h
2313
+ * Height of the rectangle
2314
+ * @return [Integer]
2315
+ *
2316
+ * @!method self.[](*args)
2317
+ * Alias of new. See {#initialize}.
2318
+ * @return [SDL2::Rect]
2319
+ */
2320
+ static VALUE Rect_s_allocate(VALUE klass)
2321
+ {
2322
+ SDL_Rect* rect = ALLOC(SDL_Rect);
2323
+ rect->x = rect->y = rect->w = rect->h = 0;
2324
+
2325
+ return Data_Wrap_Struct(cRect, 0, free, rect);
2326
+ }
2327
+
2328
+ /*
2329
+ * Create a new SDL2::Rect object
2330
+ *
2331
+ * @return [SDL2::Rect]
2332
+ *
2333
+ * @overload initialze(x, y, w, h)
2334
+ * Create a new SDL2::Rect object
2335
+ *
2336
+ * @param x [Integer] X coordiante of the left-top point of the rectangle
2337
+ * @param y [Integer] Y coordiante of the left-top point of the rectangle
2338
+ * @param w [Integer] Width of the rectangle
2339
+ * @param h [Integer] Height of the rectangle
2340
+ *
2341
+ * @overload initialize
2342
+ * Create a new SDL2::Rect object whose x, w, w, and h are all
2343
+ * zero.
2344
+ */
2345
+ static VALUE Rect_initialize(int argc, VALUE* argv, VALUE self)
2346
+ {
2347
+ VALUE x, y, w, h;
2348
+ rb_scan_args(argc, argv, "04", &x, &y, &w, &h);
2349
+ if (argc == 0) {
2350
+ /* do nothing*/
2351
+ } else if (argc == 4) {
2352
+ SDL_Rect* rect;
2353
+ Data_Get_Struct(self, SDL_Rect, rect);
2354
+ rect->x = NUM2INT(x); rect->y = NUM2INT(y);
2355
+ rect->w = NUM2INT(w); rect->h = NUM2INT(h);
2356
+ } else {
2357
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 or 4)", argc);
2358
+ }
2359
+ return Qnil;
2360
+ }
2361
+
2362
+ /*
2363
+ * Inspection string for debug
2364
+ * @return [String]
2365
+ */
2366
+ static VALUE Rect_inspect(VALUE self)
2367
+ {
2368
+ SDL_Rect* rect = Get_SDL_Rect(self);
2369
+ return rb_sprintf("<SDL2::Rect: x=%d y=%d w=%d h=%d>",
2370
+ rect->x, rect->y, rect->w, rect->h);
2371
+ }
2372
+
2373
+ FIELD_ACCESSOR(Rect, SDL_Rect, x);
2374
+ FIELD_ACCESSOR(Rect, SDL_Rect, y);
2375
+ FIELD_ACCESSOR(Rect, SDL_Rect, w);
2376
+ FIELD_ACCESSOR(Rect, SDL_Rect, h);
2377
+
2378
+ /*
2379
+ * @overload intersection(other)
2380
+ * Returns the intersection rect of self and other.
2381
+ *
2382
+ * If there is no intersection, returns nil.
2383
+ *
2384
+ * @return [SDL2::Rect, nil]
2385
+ * @param [SDL2::Rect] other rectangle
2386
+ */
2387
+ static VALUE Rect_intersection(VALUE self, VALUE other)
2388
+ {
2389
+ VALUE result = Rect_s_allocate(cRect);
2390
+ if (SDL_IntersectRect(Get_SDL_Rect(self), Get_SDL_Rect(other), Get_SDL_Rect(result))) {
2391
+ return result;
2392
+ } else {
2393
+ return Qnil;
2394
+ }
2395
+ }
2396
+
2397
+ /*
2398
+ * @overload union(other)
2399
+ * Returns the minimal rect containing self and other
2400
+ *
2401
+ * @return [SDL2::Rect]
2402
+ * @param [SDL2::Rect] other rectangle
2403
+ */
2404
+ static VALUE Rect_union(VALUE self, VALUE other)
2405
+ {
2406
+ VALUE result = Rect_s_allocate(cRect);
2407
+ SDL_UnionRect(Get_SDL_Rect(self), Get_SDL_Rect(other), Get_SDL_Rect(result));
2408
+ return result;
2409
+ }
2410
+
2411
+ /*
2412
+ * Document-class: SDL2::Point
2413
+ *
2414
+ * This class represents a point in SDL library.
2415
+ * Some method requires this method.
2416
+ *
2417
+ * @!attribute [rw] x
2418
+ * X coordiante of the point.
2419
+ * @return [Integer]
2420
+ *
2421
+ * @!attribute [rw] y
2422
+ * Y coordiante of the point.
2423
+ * @return [Integer]
2424
+ */
2425
+ static VALUE Point_s_allocate(VALUE klass)
2426
+ {
2427
+ SDL_Point* point;
2428
+ return Data_Make_Struct(klass, SDL_Point, 0, free, point);
2429
+ }
2430
+
2431
+ /*
2432
+ * Create a new point object.
2433
+ *
2434
+ * @overload initialize(x, y)
2435
+ * @param x the x coordinate of the point
2436
+ * @param y the y coordinate of the point
2437
+ *
2438
+ * @overload initialize
2439
+ * x and y of the created point object are initialized by 0
2440
+ *
2441
+ * @return [SDL2::Point]
2442
+ *
2443
+ */
2444
+ static VALUE Point_initialize(int argc, VALUE* argv, VALUE self)
2445
+ {
2446
+ VALUE x, y;
2447
+ SDL_Point* point = Get_SDL_Point(self);
2448
+ rb_scan_args(argc, argv, "02", &x, &y);
2449
+ point->x = (x == Qnil) ? 0 : NUM2INT(x);
2450
+ point->y = (y == Qnil) ? 0 : NUM2INT(y);
2451
+ return Qnil;
2452
+ }
2453
+
2454
+ /*
2455
+ * Return inspection string.
2456
+ * @return [String]
2457
+ */
2458
+ static VALUE Point_inspect(VALUE self)
2459
+ {
2460
+ SDL_Point* point = Get_SDL_Point(self);
2461
+ return rb_sprintf("<SDL2::Point x=%d y=%d>", point->x, point->y);
2462
+ }
2463
+
2464
+ FIELD_ACCESSOR(Point, SDL_Point, x);
2465
+ FIELD_ACCESSOR(Point, SDL_Point, y);
2466
+
2467
+ static VALUE PixelForamt_initialize(VALUE self, VALUE format)
2468
+ {
2469
+ rb_iv_set(self, "@format", format);
2470
+ return Qnil;
2471
+ }
2472
+
2473
+ static VALUE PixelFormat_type(VALUE self)
2474
+ {
2475
+ return UINT2NUM(SDL_PIXELTYPE(NUM2UINT(rb_iv_get(self, "@format"))));
2476
+ }
2477
+
2478
+ #define PIXELFORMAT_ATTR_READER(field, extractor, c2ruby) \
2479
+ static VALUE PixelFormat_##field(VALUE self) \
2480
+ { \
2481
+ return c2ruby(extractor(NUM2UINT(rb_iv_get(self, "@format")))); \
2482
+ }
2483
+
2484
+ PIXELFORMAT_ATTR_READER(name, SDL_GetPixelFormatName, utf8str_new_cstr);
2485
+ PIXELFORMAT_ATTR_READER(order, SDL_PIXELORDER, UINT2NUM);
2486
+ PIXELFORMAT_ATTR_READER(layout, SDL_PIXELLAYOUT, UINT2NUM);
2487
+ PIXELFORMAT_ATTR_READER(bits_per_pixel, SDL_BITSPERPIXEL, INT2NUM);
2488
+ PIXELFORMAT_ATTR_READER(bytes_per_pixel, SDL_BYTESPERPIXEL, INT2NUM);
2489
+ PIXELFORMAT_ATTR_READER(indexed_p, SDL_ISPIXELFORMAT_INDEXED, INT2BOOL);
2490
+ PIXELFORMAT_ATTR_READER(alpha_p, SDL_ISPIXELFORMAT_ALPHA, INT2BOOL);
2491
+ PIXELFORMAT_ATTR_READER(fourcc_p, SDL_ISPIXELFORMAT_FOURCC, INT2BOOL);
2492
+
2493
+ static VALUE PixelFormat_eq(VALUE self, VALUE other)
2494
+ {
2495
+ if (!rb_obj_is_kind_of(other, cPixelFormat))
2496
+ return Qfalse;
2497
+
2498
+ return INT2BOOL(rb_iv_get(self, "@format") == rb_iv_get(other, "@format"));
2499
+ }
2500
+
2501
+ static VALUE PixelFormat_inspect(VALUE self)
2502
+ {
2503
+ Uint32 format = NUM2UINT(rb_iv_get(self, "@format"));
2504
+ return rb_sprintf("<%s: %s type=%d order=%d layout=%d"
2505
+ " bits=%d bytes=%d indexed=%s alpha=%s fourcc=%s>",
2506
+ rb_obj_classname(self),
2507
+ SDL_GetPixelFormatName(format),
2508
+ SDL_PIXELTYPE(format), SDL_PIXELORDER(format), SDL_PIXELLAYOUT(format),
2509
+ SDL_BITSPERPIXEL(format), SDL_BYTESPERPIXEL(format),
2510
+ INT2BOOLCSTR(SDL_ISPIXELFORMAT_INDEXED(format)),
2511
+ INT2BOOLCSTR(SDL_ISPIXELFORMAT_ALPHA(format)),
2512
+ INT2BOOLCSTR(SDL_ISPIXELFORMAT_FOURCC(format)));
2513
+ }
2514
+
2515
+ static VALUE ScreenSaver_enable(VALUE self)
2516
+ {
2517
+ SDL_EnableScreenSaver();
2518
+ return Qnil;
2519
+ }
2520
+
2521
+ static VALUE ScreenSaver_disable(VALUE self)
2522
+ {
2523
+ SDL_DisableScreenSaver();
2524
+ return Qnil;
2525
+ }
2526
+
2527
+ static VALUE ScreenSaver_enabled_p(VALUE self)
2528
+ {
2529
+ return INT2BOOL(SDL_IsScreenSaverEnabled());
2530
+ }
2531
+
2532
+ /*
2533
+ define(`DEFINE_C_ACCESSOR',`rb_define_method($2, "$3", $1_$3, 0);
2534
+ rb_define_method($2, "$3=", $1_set_$3, 1)')
2535
+ */
2536
+
2537
+ void rubysdl2_init_video(void)
2538
+ {
2539
+ rb_define_module_function(mSDL2, "video_drivers", SDL2_s_video_drivers, 0);
2540
+ rb_define_module_function(mSDL2, "current_video_driver", SDL2_s_current_video_driver, 0);
2541
+ rb_define_module_function(mSDL2, "video_init", SDL2_s_video_init, 1);
2542
+
2543
+ cWindow = rb_define_class_under(mSDL2, "Window", rb_cObject);
2544
+
2545
+ rb_undef_alloc_func(cWindow);
2546
+ rb_define_singleton_method(cWindow, "create", Window_s_create, 6);
2547
+ rb_define_singleton_method(cWindow, "all_windows", Window_s_all_windows, 0);
2548
+ rb_define_singleton_method(cWindow, "find_by_id", Window_s_find_by_id, 1);
2549
+ rb_define_method(cWindow, "destroy?", Window_destroy_p, 0);
2550
+ rb_define_method(cWindow, "destroy", Window_destroy, 0);
2551
+ rb_define_method(cWindow, "create_renderer", Window_create_renderer, 2);
2552
+ rb_define_method(cWindow, "renderer", Window_renderer, 0);
2553
+ rb_define_method(cWindow, "window_id", Window_window_id, 0);
2554
+ rb_define_method(cWindow, "inspect", Window_inspect, 0);
2555
+ rb_define_method(cWindow, "display_mode", Window_display_mode, 0);
2556
+ rb_define_method(cWindow, "display", Window_display, 0);
2557
+ rb_define_method(cWindow, "debug_info", Window_debug_info, 0);
2558
+ DEFINE_C_ACCESSOR(Window, cWindow, brightness);
2559
+ rb_define_method(cWindow, "flags", Window_flags, 0);
2560
+ rb_define_method(cWindow, "gamma_ramp", Window_gamma_ramp, 0);
2561
+ rb_define_method(cWindow, "input_is_grabbed?", Window_input_is_grabbed_p, 0);
2562
+ rb_define_method(cWindow, "input_is_grabbed=", Window_set_input_is_grabbed, 1);
2563
+ DEFINE_C_ACCESSOR(Window, cWindow, maximum_size);
2564
+ DEFINE_C_ACCESSOR(Window, cWindow, minimum_size);
2565
+ DEFINE_C_ACCESSOR(Window, cWindow, position);
2566
+ DEFINE_C_ACCESSOR(Window, cWindow, size);
2567
+ DEFINE_C_ACCESSOR(Window, cWindow, title);
2568
+ DEFINE_C_ACCESSOR(Window, cWindow, bordered);
2569
+ rb_define_method(cWindow, "icon=", Window_set_icon, 1);
2570
+ rb_define_method(cWindow, "show", Window_show, 0);
2571
+ rb_define_method(cWindow, "hide", Window_hide, 0);
2572
+ rb_define_method(cWindow, "maximize", Window_maximize, 0);
2573
+ rb_define_method(cWindow, "minimize", Window_minimize, 0);
2574
+ rb_define_method(cWindow, "raise", Window_raise, 0);
2575
+ rb_define_method(cWindow, "restore", Window_restore, 0);
2576
+ rb_define_method(cWindow, "fullscreen_mode", Window_fullscreen_mode, 0);
2577
+ rb_define_method(cWindow, "fullscreen_mode=", Window_set_fullscreen_mode, 1);
2578
+ #if SDL_VERSION_ATLEAST(2,0,1)
2579
+ rb_define_method(cWindow, "gl_drawable_size", Window_gl_drawable_size, 0);
2580
+ #endif
2581
+ rb_define_method(cWindow, "gl_swap", Window_gl_swap, 0);
2582
+ rb_define_const(cWindow, "POS_CENTERED", INT2NUM(SDL_WINDOWPOS_CENTERED));
2583
+ rb_define_const(cWindow, "POS_UNDEFINED", INT2NUM(SDL_WINDOWPOS_UNDEFINED));
2584
+ #define DEFINE_SDL_WINDOW_FLAGS_CONST(n) \
2585
+ rb_define_const(cWindow, #n, UINT2NUM(SDL_WINDOW_##n));
2586
+ DEFINE_SDL_WINDOW_FLAGS_CONST(FULLSCREEN);
2587
+ DEFINE_SDL_WINDOW_FLAGS_CONST(FULLSCREEN_DESKTOP);
2588
+ DEFINE_SDL_WINDOW_FLAGS_CONST(OPENGL);
2589
+ DEFINE_SDL_WINDOW_FLAGS_CONST(SHOWN);
2590
+ DEFINE_SDL_WINDOW_FLAGS_CONST(HIDDEN);
2591
+ DEFINE_SDL_WINDOW_FLAGS_CONST(BORDERLESS);
2592
+ DEFINE_SDL_WINDOW_FLAGS_CONST(RESIZABLE);
2593
+ DEFINE_SDL_WINDOW_FLAGS_CONST(MINIMIZED);
2594
+ DEFINE_SDL_WINDOW_FLAGS_CONST(MAXIMIZED);
2595
+ DEFINE_SDL_WINDOW_FLAGS_CONST(INPUT_GRABBED);
2596
+ DEFINE_SDL_WINDOW_FLAGS_CONST(INPUT_FOCUS);
2597
+ DEFINE_SDL_WINDOW_FLAGS_CONST(MOUSE_FOCUS);
2598
+ DEFINE_SDL_WINDOW_FLAGS_CONST(FOREIGN);
2599
+ #ifdef SDL_WINDOW_ALLOW_HIGHDPI
2600
+ DEFINE_SDL_WINDOW_FLAGS_CONST(ALLOW_HIGHDPI);
2601
+ #endif
2602
+
2603
+
2604
+ cDisplay = rb_define_class_under(mSDL2, "Display", rb_cObject);
2605
+
2606
+ rb_define_module_function(cDisplay, "displays", Display_s_displays, 0);
2607
+ rb_define_attr(cDisplay, "index", 1, 0);
2608
+ rb_define_attr(cDisplay, "name", 1, 0);
2609
+ rb_define_method(cDisplay, "modes", Display_modes, 0);
2610
+ rb_define_method(cDisplay, "current_mode", Display_current_mode, 0);
2611
+ rb_define_method(cDisplay, "desktop_mode", Display_desktop_mode, 0);
2612
+ rb_define_method(cDisplay, "closest_mode", Display_closest_mode, 1);
2613
+ rb_define_method(cDisplay, "bounds", Display_bounds, 0);
2614
+
2615
+ cDisplayMode = rb_define_class_under(cDisplay, "Mode", rb_cObject);
2616
+
2617
+ rb_define_alloc_func(cDisplayMode, DisplayMode_s_allocate);
2618
+ rb_define_method(cDisplayMode, "initialize", DisplayMode_initialize, 4);
2619
+ rb_define_method(cDisplayMode, "inspect", DisplayMode_inspect, 0);
2620
+ rb_define_method(cDisplayMode, "format", DisplayMode_format, 0);
2621
+ rb_define_method(cDisplayMode, "w", DisplayMode_w, 0);
2622
+ rb_define_method(cDisplayMode, "h", DisplayMode_h, 0);
2623
+ rb_define_method(cDisplayMode, "refresh_rate", DisplayMode_refresh_rate, 0);
2624
+ /* attr format, w, h, refresh_rate */
2625
+
2626
+ cRenderer = rb_define_class_under(mSDL2, "Renderer", rb_cObject);
2627
+
2628
+ rb_undef_alloc_func(cRenderer);
2629
+ rb_define_singleton_method(cRenderer, "drivers_info", Renderer_s_drivers_info, 0);
2630
+ rb_define_method(cRenderer, "destroy?", Renderer_destroy_p, 0);
2631
+ rb_define_method(cRenderer, "destroy", Renderer_destroy, 0);
2632
+ rb_define_method(cRenderer, "debug_info", Renderer_debug_info, 0);
2633
+ rb_define_method(cRenderer, "create_texture", Renderer_create_texture, 4);
2634
+ rb_define_method(cRenderer, "create_texture_from", Renderer_create_texture_from, 1);
2635
+ rb_define_method(cRenderer, "copy", Renderer_copy, 3);
2636
+ rb_define_method(cRenderer, "copy_ex", Renderer_copy_ex, 6);
2637
+ rb_define_method(cRenderer, "present", Renderer_present, 0);
2638
+ rb_define_method(cRenderer, "draw_color",Renderer_draw_color, 0);
2639
+ rb_define_method(cRenderer, "draw_color=",Renderer_set_draw_color, 1);
2640
+ rb_define_method(cRenderer, "clear", Renderer_clear, 0);
2641
+ rb_define_method(cRenderer, "draw_line",Renderer_draw_line, 4);
2642
+ rb_define_method(cRenderer, "draw_point",Renderer_draw_point, 2);
2643
+ rb_define_method(cRenderer, "draw_rect", Renderer_draw_rect, 1);
2644
+ rb_define_method(cRenderer, "fill_rect", Renderer_fill_rect, 1);
2645
+ rb_define_method(cRenderer, "draw_blend_mode", Renderer_draw_blend_mode, 0);
2646
+ rb_define_method(cRenderer, "draw_blend_mode=", Renderer_set_draw_blend_mode, 1);
2647
+ rb_define_method(cRenderer, "clip_rect", Renderer_clip_rect, 0);
2648
+ #if SDL_VERSION_ATLEAST(2,0,4)
2649
+ rb_define_method(cRenderer, "clip_enabled?", Render_clip_enabled_p, 0);
2650
+ #endif
2651
+ rb_define_method(cRenderer, "logical_size", Renderer_logical_size, 0);
2652
+ rb_define_method(cRenderer, "scale", Renderer_scale, 0);
2653
+ rb_define_method(cRenderer, "viewport", Renderer_viewport, 0);
2654
+ rb_define_method(cRenderer, "support_render_target?", Renderer_support_render_target_p, 0);
2655
+ rb_define_method(cRenderer, "output_size", Renderer_output_size, 0);
2656
+ rb_define_method(cRenderer, "render_target", Renderer_render_target, 0);
2657
+ rb_define_method(cRenderer, "render_target=", Renderer_set_render_target, 1);
2658
+ rb_define_method(cRenderer, "reset_render_target", Renderer_reset_render_target, 0);
2659
+
2660
+ rb_define_method(cRenderer, "info", Renderer_info, 0);
2661
+ #define DEFINE_SDL_RENDERER_FLAGS_CONST(n) \
2662
+ rb_define_const(cRenderer, #n, UINT2NUM(SDL_RENDERER_##n))
2663
+ DEFINE_SDL_RENDERER_FLAGS_CONST(SOFTWARE);
2664
+ DEFINE_SDL_RENDERER_FLAGS_CONST(ACCELERATED);
2665
+ #ifdef SDL_RENDERER_PRESENTVSYNC
2666
+ DEFINE_SDL_RENDERER_FLAGS_CONST(PRESENTVSYNC);
2667
+ #endif
2668
+ DEFINE_SDL_RENDERER_FLAGS_CONST(TARGETTEXTURE);
2669
+ #define DEFINE_SDL_FLIP_CONST(t) \
2670
+ rb_define_const(cRenderer, "FLIP_" #t, INT2FIX(SDL_FLIP_##t))
2671
+ DEFINE_SDL_FLIP_CONST(NONE);
2672
+ DEFINE_SDL_FLIP_CONST(HORIZONTAL);
2673
+ DEFINE_SDL_FLIP_CONST(VERTICAL);
2674
+ #define DEFINE_BLENDMODE_CONST(t) \
2675
+ rb_define_const(mSDL2, "BLENDMODE_" #t, INT2FIX(SDL_BLENDMODE_##t))
2676
+ DEFINE_BLENDMODE_CONST(NONE);
2677
+ DEFINE_BLENDMODE_CONST(BLEND);
2678
+ DEFINE_BLENDMODE_CONST(ADD);
2679
+ DEFINE_BLENDMODE_CONST(MOD);
2680
+
2681
+ cTexture = rb_define_class_under(mSDL2, "Texture", rb_cObject);
2682
+
2683
+ rb_undef_alloc_func(cTexture);
2684
+ rb_define_method(cTexture, "destroy?", Texture_destroy_p, 0);
2685
+ rb_define_method(cTexture, "destroy", Texture_destroy, 0);
2686
+ DEFINE_C_ACCESSOR(Texture, cTexture, blend_mode);
2687
+ DEFINE_C_ACCESSOR(Texture, cTexture, color_mod);
2688
+ DEFINE_C_ACCESSOR(Texture, cTexture, alpha_mod);
2689
+ rb_define_method(cTexture, "format", Texture_format, 0);
2690
+ rb_define_method(cTexture, "access_pattern", Texture_access_pattern, 0);
2691
+ rb_define_method(cTexture, "w", Texture_w, 0);
2692
+ rb_define_method(cTexture, "h", Texture_h, 0);
2693
+ rb_define_method(cTexture, "inspect", Texture_inspect, 0);
2694
+ rb_define_method(cTexture, "debug_info", Texture_debug_info, 0);
2695
+ #define DEFINE_TEXTUREAH_ACCESS_CONST(t) \
2696
+ rb_define_const(cTexture, "ACCESS_" #t, INT2NUM(SDL_TEXTUREACCESS_##t))
2697
+ DEFINE_TEXTUREAH_ACCESS_CONST(STATIC);
2698
+ DEFINE_TEXTUREAH_ACCESS_CONST(STREAMING);
2699
+ DEFINE_TEXTUREAH_ACCESS_CONST(TARGET);
2700
+
2701
+
2702
+ cSurface = rb_define_class_under(mSDL2, "Surface", rb_cObject);
2703
+
2704
+ rb_undef_alloc_func(cSurface);
2705
+ rb_define_singleton_method(cSurface, "load_bmp", Surface_s_load_bmp, 1);
2706
+ rb_define_singleton_method(cSurface, "blit", Surface_s_blit, 4);
2707
+ rb_define_singleton_method(cSurface, "new", Surface_s_new, -1);
2708
+ rb_define_singleton_method(cSurface, "from_string", Surface_s_from_string, -1);
2709
+ rb_define_method(cSurface, "destroy?", Surface_destroy_p, 0);
2710
+ rb_define_method(cSurface, "destroy", Surface_destroy, 0);
2711
+ DEFINE_C_ACCESSOR(Surface, cSurface, blend_mode);
2712
+ rb_define_method(cSurface, "must_lock?", Surface_must_lock_p, 0);
2713
+ rb_define_method(cSurface, "lock", Surface_lock, 0);
2714
+ rb_define_method(cSurface, "unlock", Surface_unlock, 0);
2715
+ rb_define_method(cSurface, "w", Surface_w, 0);
2716
+ rb_define_method(cSurface, "h", Surface_h, 0);
2717
+ rb_define_method(cSurface, "pixel", Surface_pixel, 2);
2718
+ rb_define_method(cSurface, "pixel_color", Surface_pixel_color, 2);
2719
+ rb_define_method(cSurface, "color_key", Surface_color_key, 0);
2720
+ rb_define_method(cSurface, "color_key=", Surface_set_color_key, 1);
2721
+ rb_define_method(cSurface, "unset_color_key", Surface_set_color_key, 0);
2722
+ rb_define_method(cSurface, "pixels", Surface_pixels, 0);
2723
+ rb_define_method(cSurface, "pitch", Surface_pitch, 0);
2724
+ rb_define_method(cSurface, "bits_per_pixel", Surface_bits_per_pixel, 0);
2725
+ rb_define_method(cSurface, "bytes_per_pixel", Surface_bytes_per_pixel, 0);
2726
+
2727
+ cRect = rb_define_class_under(mSDL2, "Rect", rb_cObject);
2728
+
2729
+ rb_define_alloc_func(cRect, Rect_s_allocate);
2730
+ rb_define_method(cRect, "initialize", Rect_initialize, -1);
2731
+ rb_define_alias(rb_singleton_class(cRect), "[]", "new");
2732
+ rb_define_method(cRect, "inspect", Rect_inspect, 0);
2733
+ DEFINE_C_ACCESSOR(Rect, cRect, x);
2734
+ DEFINE_C_ACCESSOR(Rect, cRect, y);
2735
+ DEFINE_C_ACCESSOR(Rect, cRect, w);
2736
+ DEFINE_C_ACCESSOR(Rect, cRect, h);
2737
+ rb_define_method(cRect, "union", Rect_union, 1);
2738
+ rb_define_method(cRect, "intersection", Rect_intersection, 1);
2739
+
2740
+ cPoint = rb_define_class_under(mSDL2, "Point", rb_cObject);
2741
+
2742
+ rb_define_alloc_func(cPoint, Point_s_allocate);
2743
+ rb_define_method(cPoint, "initialize", Point_initialize, -1);
2744
+ rb_define_alias(rb_singleton_class(cPoint), "[]", "new");
2745
+ rb_define_method(cPoint, "inspect", Point_inspect, 0);
2746
+ DEFINE_C_ACCESSOR(Point, cPoint, x);
2747
+ DEFINE_C_ACCESSOR(Point, cPoint, y);
2748
+
2749
+
2750
+ cRendererInfo = rb_define_class_under(cRenderer, "Info", rb_cObject);
2751
+ define_attr_readers(cRendererInfo, "name", "flags", "texture_formats",
2752
+ "max_texture_width", "max_texture_height", NULL);
2753
+
2754
+
2755
+ cPixelFormat = rb_define_class_under(mSDL2, "PixelFormat", rb_cObject);
2756
+
2757
+ rb_define_method(cPixelFormat, "initialize", PixelForamt_initialize, 1);
2758
+ rb_define_attr(cPixelFormat, "format", 1, 0);
2759
+ rb_define_method(cPixelFormat, "name", PixelFormat_name, 0);
2760
+ rb_define_method(cPixelFormat, "inspect", PixelFormat_inspect, 0);
2761
+ rb_define_method(cPixelFormat, "type", PixelFormat_type, 0);
2762
+ rb_define_method(cPixelFormat, "order", PixelFormat_order, 0);
2763
+ rb_define_method(cPixelFormat, "layout", PixelFormat_layout, 0);
2764
+ rb_define_method(cPixelFormat, "bits_per_pixel", PixelFormat_bits_per_pixel, 0);
2765
+ rb_define_alias(cPixelFormat, "bpp", "bits_per_pixel");
2766
+ rb_define_method(cPixelFormat, "bytes_per_pixel", PixelFormat_bytes_per_pixel, 0);
2767
+ rb_define_method(cPixelFormat, "indexed?", PixelFormat_indexed_p, 0);
2768
+ rb_define_method(cPixelFormat, "alpha?", PixelFormat_alpha_p, 0);
2769
+ rb_define_method(cPixelFormat, "fourcc?", PixelFormat_fourcc_p, 0);
2770
+ rb_define_method(cPixelFormat, "==", PixelFormat_eq, 1);
2771
+
2772
+ {
2773
+ VALUE formats = rb_ary_new();
2774
+ rb_define_const(cPixelFormat, "FORMATS", formats);
2775
+ #define DEFINE_PIXELFORMAT_CONST(t) \
2776
+ do { \
2777
+ VALUE format = PixelFormat_new(SDL_PIXELFORMAT_##t); \
2778
+ rb_define_const(cPixelFormat, #t, format); \
2779
+ rb_ary_push(formats, format); \
2780
+ } while (0)
2781
+ DEFINE_PIXELFORMAT_CONST(UNKNOWN);
2782
+ DEFINE_PIXELFORMAT_CONST(INDEX1LSB);
2783
+ DEFINE_PIXELFORMAT_CONST(INDEX1MSB);
2784
+ DEFINE_PIXELFORMAT_CONST(INDEX4LSB);
2785
+ DEFINE_PIXELFORMAT_CONST(INDEX4MSB);
2786
+ DEFINE_PIXELFORMAT_CONST(INDEX8);
2787
+ DEFINE_PIXELFORMAT_CONST(RGB332);
2788
+ DEFINE_PIXELFORMAT_CONST(RGB444);
2789
+ DEFINE_PIXELFORMAT_CONST(RGB555);
2790
+ DEFINE_PIXELFORMAT_CONST(BGR555);
2791
+ DEFINE_PIXELFORMAT_CONST(ARGB4444);
2792
+ DEFINE_PIXELFORMAT_CONST(RGBA4444);
2793
+ DEFINE_PIXELFORMAT_CONST(ABGR4444);
2794
+ DEFINE_PIXELFORMAT_CONST(BGRA4444);
2795
+ DEFINE_PIXELFORMAT_CONST(ARGB1555);
2796
+ DEFINE_PIXELFORMAT_CONST(RGBA5551);
2797
+ DEFINE_PIXELFORMAT_CONST(ABGR1555);
2798
+ DEFINE_PIXELFORMAT_CONST(BGRA5551);
2799
+ DEFINE_PIXELFORMAT_CONST(RGB565);
2800
+ DEFINE_PIXELFORMAT_CONST(BGR565);
2801
+ DEFINE_PIXELFORMAT_CONST(RGB24);
2802
+ DEFINE_PIXELFORMAT_CONST(BGR24);
2803
+ DEFINE_PIXELFORMAT_CONST(RGB888);
2804
+ DEFINE_PIXELFORMAT_CONST(RGBX8888);
2805
+ DEFINE_PIXELFORMAT_CONST(BGR888);
2806
+ DEFINE_PIXELFORMAT_CONST(BGRX8888);
2807
+ DEFINE_PIXELFORMAT_CONST(ARGB8888);
2808
+ DEFINE_PIXELFORMAT_CONST(RGBA8888);
2809
+ DEFINE_PIXELFORMAT_CONST(ABGR8888);
2810
+ DEFINE_PIXELFORMAT_CONST(BGRA8888);
2811
+ DEFINE_PIXELFORMAT_CONST(ARGB2101010);
2812
+ DEFINE_PIXELFORMAT_CONST(YV12);
2813
+ DEFINE_PIXELFORMAT_CONST(IYUV);
2814
+ DEFINE_PIXELFORMAT_CONST(YUY2);
2815
+ DEFINE_PIXELFORMAT_CONST(UYVY);
2816
+ DEFINE_PIXELFORMAT_CONST(YVYU);
2817
+ rb_obj_freeze(formats);
2818
+ }
2819
+
2820
+ mScreenSaver = rb_define_module_under(mSDL2, "ScreenSaver");
2821
+ rb_define_module_function(mScreenSaver, "enable", ScreenSaver_enable, 0);
2822
+ rb_define_module_function(mScreenSaver, "disable", ScreenSaver_disable, 0);
2823
+ rb_define_module_function(mScreenSaver, "enabled?", ScreenSaver_enabled_p, 0);
2824
+
2825
+
2826
+ rb_gc_register_address(&hash_windowid_to_window);
2827
+ hash_windowid_to_window = rb_hash_new();
2828
+ }
2829
+
2830
+ #ifdef HAVE_SDL_IMAGE_H
2831
+ #include <SDL_image.h>
2832
+
2833
+ static VALUE mIMG;
2834
+
2835
+ /*
2836
+ * @overload init(flags)
2837
+ * Initialize SDL_image.
2838
+ *
2839
+ * You can specify the supporting image formats by bitwise OR'd of the
2840
+ * following constants.
2841
+ *
2842
+ * * {SDL2::IMG::INIT_JPG}
2843
+ * * {SDL2::IMG::INIT_PNG}
2844
+ * * {SDL2::IMG::INIT_TIF}
2845
+ *
2846
+ * You need to initialize SDL_image to check whether specified format
2847
+ * is supported by your environment. If your environment does not
2848
+ * support required support format, you have a {SDL2::Error} exception.
2849
+ *
2850
+ * @param [Integer] flags submodule bits
2851
+ * @return [nil]
2852
+ *
2853
+ * @raise [SDL2::Error] raised when initializing is failed.
2854
+ */
2855
+ static VALUE IMG_s_init(VALUE self, VALUE f)
2856
+ {
2857
+ int flags = NUM2INT(f);
2858
+ if (IMG_Init(flags) & flags != flags)
2859
+ rb_raise(eSDL2Error, "Couldn't initialze SDL_image");
2860
+ return Qnil;
2861
+ }
2862
+
2863
+ /*
2864
+ * @overload load(file)
2865
+ * Load file and create a new {SDL2::Surface}.
2866
+ *
2867
+ * This method uses SDL_image. SDL_image supports following formats:
2868
+ * BMP, CUR, GIF, ICO, JPG, LBP, PCX, PNG, PNM, TGA, TIF, XCF, XPM, and XV.
2869
+ *
2870
+ * @param [String] file the image file name to load a surface from
2871
+ * @return [SDL2::Surface] Created surface
2872
+ *
2873
+ * @raise [SDL2::Error] raised when you fail to load (for example,
2874
+ * you have a wrong file name, or the file is broken)
2875
+ *
2876
+ * @see SDL2::IMG.init
2877
+ * @see SDL2::Renderer#load_texture
2878
+ */
2879
+ static VALUE Surface_s_load(VALUE self, VALUE fname)
2880
+ {
2881
+ SDL_Surface* surface = IMG_Load(StringValueCStr(fname));
2882
+ if (!surface) {
2883
+ SDL_SetError(IMG_GetError());
2884
+ SDL_ERROR();
2885
+ }
2886
+ return Surface_new(surface);
2887
+ }
2888
+
2889
+ /*
2890
+ * @overload load_texture(file)
2891
+ *
2892
+ * Load file and create a new {SDL2::Texture}.
2893
+ *
2894
+ * This method uses SDL_image. SDL_image supports following formats:
2895
+ * BMP, CUR, GIF, ICO, JPG, LBP, PCX, PNG, PNM, TGA, TIF, XCF, XPM, and XV.
2896
+ *
2897
+ * @param [String] file the image file name to load a texture from
2898
+ * @return [SDL2::Texture] Created texture
2899
+ *
2900
+ * @raise [SDL2::Error] raised when you fail to load (for example,
2901
+ * you have a wrong file name, or the file is broken)
2902
+ *
2903
+ * @see SDL2::IMG.init
2904
+ * @see SDL2::Surface.load
2905
+ */
2906
+ static VALUE Renderer_load_texture(VALUE self, VALUE fname)
2907
+ {
2908
+ SDL_Texture* texture = IMG_LoadTexture(Get_SDL_Renderer(self), StringValueCStr(fname));
2909
+ if (!texture) {
2910
+ SDL_SetError(IMG_GetError());
2911
+ SDL_ERROR();
2912
+ }
2913
+ return Texture_new(texture, Get_Renderer(self));
2914
+ }
2915
+
2916
+ void rubysdl2_init_image(void)
2917
+ {
2918
+ mIMG = rb_define_module_under(mSDL2, "IMG");
2919
+ rb_define_module_function(mIMG, "init", IMG_s_init, 1);
2920
+
2921
+ rb_define_singleton_method(cSurface, "load", Surface_s_load, 1);
2922
+ rb_define_method(cRenderer, "load_texture", Renderer_load_texture, 1);
2923
+
2924
+
2925
+ rb_define_const(mIMG, "INIT_JPG", INT2NUM(IMG_INIT_JPG));
2926
+ rb_define_const(mIMG, "INIT_PNG", INT2NUM(IMG_INIT_PNG));
2927
+ rb_define_const(mIMG, "INIT_TIF", INT2NUM(IMG_INIT_TIF));
2928
+ rb_define_const(mIMG, "INIT_WEBP", INT2NUM(IMG_INIT_WEBP));
2929
+ }
2930
+
2931
+ #else /* HAVE_SDL_IMAGE_H */
2932
+ void rubysdl2_init_image(void)
2933
+ {
2934
+ }
2935
+ #endif