ruby2d 0.11.2 → 0.12.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.
Files changed (231) hide show
  1. checksums.yaml +4 -4
  2. data/assets/include/GLES2/gl2.h +656 -0
  3. data/assets/include/GLES2/gl2ext.h +3949 -0
  4. data/assets/include/GLES2/gl2ext_angle.h +701 -0
  5. data/assets/include/GLES2/gl2platform.h +27 -0
  6. data/assets/include/GLES3/gl3.h +1192 -0
  7. data/assets/include/GLES3/gl31.h +1507 -0
  8. data/assets/include/GLES3/gl32.h +1808 -0
  9. data/assets/include/GLES3/gl3platform.h +27 -0
  10. data/assets/include/KHR/khrplatform.h +290 -0
  11. data/assets/include/SDL2/SDL.h +1 -0
  12. data/assets/include/SDL2/SDL_assert.h +4 -2
  13. data/assets/include/SDL2/SDL_atomic.h +20 -0
  14. data/assets/include/SDL2/SDL_audio.h +40 -4
  15. data/assets/include/SDL2/SDL_blendmode.h +4 -6
  16. data/assets/include/SDL2/SDL_clipboard.h +47 -0
  17. data/assets/include/SDL2/SDL_config.h +6 -2
  18. data/assets/include/SDL2/SDL_config_android.h +2 -0
  19. data/assets/include/SDL2/SDL_config_emscripten.h +2 -0
  20. data/assets/include/SDL2/SDL_config_iphoneos.h +3 -1
  21. data/assets/include/SDL2/SDL_config_macosx.h +3 -6
  22. data/assets/include/SDL2/SDL_config_minimal.h +18 -11
  23. data/assets/include/SDL2/SDL_config_ngage.h +89 -0
  24. data/assets/include/SDL2/SDL_config_os2.h +5 -3
  25. data/assets/include/SDL2/SDL_config_pandora.h +1 -0
  26. data/assets/include/SDL2/SDL_config_windows.h +71 -45
  27. data/assets/include/SDL2/SDL_config_wingdk.h +253 -0
  28. data/assets/include/SDL2/SDL_config_winrt.h +11 -49
  29. data/assets/include/SDL2/SDL_config_xbox.h +235 -0
  30. data/assets/include/SDL2/SDL_cpuinfo.h +39 -4
  31. data/assets/include/SDL2/SDL_egl.h +59 -9
  32. data/assets/include/SDL2/SDL_endian.h +34 -3
  33. data/assets/include/SDL2/SDL_events.h +32 -1
  34. data/assets/include/SDL2/SDL_filesystem.h +5 -1
  35. data/assets/include/SDL2/SDL_gamecontroller.h +78 -5
  36. data/assets/include/SDL2/SDL_guid.h +100 -0
  37. data/assets/include/SDL2/SDL_hints.h +645 -43
  38. data/assets/include/SDL2/SDL_image.h +2045 -33
  39. data/assets/include/SDL2/SDL_joystick.h +127 -7
  40. data/assets/include/SDL2/SDL_keyboard.h +38 -1
  41. data/assets/include/SDL2/SDL_keycode.h +6 -1
  42. data/assets/include/SDL2/SDL_log.h +2 -2
  43. data/assets/include/SDL2/SDL_main.h +42 -2
  44. data/assets/include/SDL2/SDL_metal.h +2 -1
  45. data/assets/include/SDL2/SDL_mixer.h +2529 -396
  46. data/assets/include/SDL2/SDL_mouse.h +12 -1
  47. data/assets/include/SDL2/SDL_opengl.h +0 -51
  48. data/assets/include/SDL2/SDL_opengl_glext.h +2260 -231
  49. data/assets/include/SDL2/SDL_opengles2_gl2.h +374 -339
  50. data/assets/include/SDL2/SDL_opengles2_gl2ext.h +3479 -1496
  51. data/assets/include/SDL2/SDL_opengles2_gl2platform.h +6 -9
  52. data/assets/include/SDL2/SDL_opengles2_khrplatform.h +43 -14
  53. data/assets/include/SDL2/SDL_platform.h +32 -6
  54. data/assets/include/SDL2/SDL_rect.h +154 -2
  55. data/assets/include/SDL2/SDL_render.h +46 -17
  56. data/assets/include/SDL2/SDL_revision.h +4 -0
  57. data/assets/include/SDL2/SDL_rwops.h +1 -15
  58. data/assets/include/SDL2/SDL_scancode.h +46 -21
  59. data/assets/include/SDL2/SDL_sensor.h +24 -3
  60. data/assets/include/SDL2/SDL_stdinc.h +119 -8
  61. data/assets/include/SDL2/SDL_surface.h +3 -1
  62. data/assets/include/SDL2/SDL_system.h +66 -6
  63. data/assets/include/SDL2/SDL_syswm.h +2 -0
  64. data/assets/include/SDL2/SDL_test_common.h +1 -0
  65. data/assets/include/SDL2/SDL_test_font.h +90 -3
  66. data/assets/include/SDL2/SDL_thread.h +3 -3
  67. data/assets/include/SDL2/SDL_touch.h +8 -0
  68. data/assets/include/SDL2/SDL_ttf.h +2084 -155
  69. data/assets/include/SDL2/SDL_version.h +19 -3
  70. data/assets/include/SDL2/SDL_video.h +71 -9
  71. data/assets/include/SDL2/begin_code.h +4 -4
  72. data/assets/include/mrbconf.h +15 -17
  73. data/assets/include/mruby/array.h +8 -21
  74. data/assets/include/mruby/boxing_nan.h +115 -86
  75. data/assets/include/mruby/boxing_word.h +104 -78
  76. data/assets/include/mruby/common.h +6 -0
  77. data/assets/include/mruby/compile.h +3 -4
  78. data/assets/include/mruby/debug.h +4 -2
  79. data/assets/include/mruby/dump.h +5 -2
  80. data/assets/include/mruby/error.h +12 -2
  81. data/assets/include/mruby/gc.h +2 -0
  82. data/assets/include/mruby/hash.h +1 -3
  83. data/assets/include/mruby/irep.h +4 -4
  84. data/assets/include/mruby/numeric.h +21 -13
  85. data/assets/include/mruby/opcode.h +30 -0
  86. data/assets/include/mruby/ops.h +99 -101
  87. data/assets/include/mruby/presym/scanning.h +15 -9
  88. data/assets/include/mruby/proc.h +4 -2
  89. data/assets/include/mruby/string.h +3 -24
  90. data/assets/include/mruby/value.h +80 -40
  91. data/assets/include/mruby/variable.h +0 -15
  92. data/assets/include/mruby/version.h +5 -5
  93. data/assets/include/mruby.h +86 -16
  94. data/assets/macos/universal/bin/mrbc +0 -0
  95. data/assets/macos/universal/lib/libFLAC.a +0 -0
  96. data/assets/macos/universal/lib/libSDL2.a +0 -0
  97. data/assets/macos/universal/lib/libSDL2_image.a +0 -0
  98. data/assets/macos/universal/lib/libSDL2_mixer.a +0 -0
  99. data/assets/macos/universal/lib/libSDL2_ttf.a +0 -0
  100. data/assets/macos/universal/lib/libavif.a +0 -0
  101. data/assets/macos/universal/lib/libbrotlicommon-static.a +0 -0
  102. data/assets/macos/universal/lib/libbrotlidec-static.a +0 -0
  103. data/assets/macos/universal/lib/libfreetype.a +0 -0
  104. data/assets/macos/universal/lib/libgraphite2.a +0 -0
  105. data/assets/macos/universal/lib/libharfbuzz.a +0 -0
  106. data/assets/macos/universal/lib/libhwy.a +0 -0
  107. data/assets/macos/universal/lib/libjpeg.a +0 -0
  108. data/assets/macos/universal/lib/libjxl.a +0 -0
  109. data/assets/macos/universal/lib/libmodplug.a +0 -0
  110. data/assets/macos/universal/lib/libmpg123.a +0 -0
  111. data/assets/macos/universal/lib/libmruby.a +0 -0
  112. data/assets/macos/universal/lib/libogg.a +0 -0
  113. data/assets/macos/universal/lib/libpng.a +0 -0
  114. data/assets/macos/universal/lib/libtiff.a +0 -0
  115. data/assets/macos/universal/lib/libvorbis.a +0 -0
  116. data/assets/macos/universal/lib/libvorbisfile.a +0 -0
  117. data/assets/macos/universal/lib/libwebp.a +0 -0
  118. data/assets/macos/universal/lib/libzstd.a +0 -0
  119. data/assets/wasm/libmruby.a +0 -0
  120. data/assets/wasm/template.html +52 -4
  121. data/assets/windows/mingw-w64-ucrt-x86_64/bin/mrbc.exe +0 -0
  122. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libFLAC.a +0 -0
  123. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libLerc.a +0 -0
  124. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2.a +0 -0
  125. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_image.a +0 -0
  126. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_mixer.a +0 -0
  127. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_ttf.a +0 -0
  128. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlicommon.a +0 -0
  129. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlidec.a +0 -0
  130. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbz2.a +0 -0
  131. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libdeflate.a +0 -0
  132. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libfreetype.a +0 -0
  133. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libglew32.a +0 -0
  134. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libgraphite2.a +0 -0
  135. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libharfbuzz.a +0 -0
  136. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libhwy.a +0 -0
  137. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjbig.a +0 -0
  138. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjpeg.a +0 -0
  139. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjxl.a +0 -0
  140. data/assets/windows/mingw-w64-ucrt-x86_64/lib/liblzma.a +0 -0
  141. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmodplug.a +0 -0
  142. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmpg123.a +0 -0
  143. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmruby.a +0 -0
  144. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libogg.a +0 -0
  145. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopus.a +0 -0
  146. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopusfile.a +0 -0
  147. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libpng.a +0 -0
  148. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libsndfile.a +0 -0
  149. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libssp.a +1 -0
  150. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libstdc++.a +0 -0
  151. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libtiff.a +0 -0
  152. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbis.a +0 -0
  153. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbisfile.a +0 -0
  154. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libwebp.a +0 -0
  155. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libz.a +0 -0
  156. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libzstd.a +0 -0
  157. data/assets/windows/mingw-w64-x86_64/bin/mrbc.exe +0 -0
  158. data/assets/windows/mingw-w64-x86_64/lib/libFLAC.a +0 -0
  159. data/assets/windows/mingw-w64-x86_64/lib/libLerc.a +0 -0
  160. data/assets/windows/mingw-w64-x86_64/lib/libSDL2.a +0 -0
  161. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_image.a +0 -0
  162. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_mixer.a +0 -0
  163. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_ttf.a +0 -0
  164. data/assets/windows/mingw-w64-x86_64/lib/libbrotlicommon.a +0 -0
  165. data/assets/windows/mingw-w64-x86_64/lib/libbrotlidec.a +0 -0
  166. data/assets/windows/mingw-w64-x86_64/lib/libdeflate.a +0 -0
  167. data/assets/windows/mingw-w64-x86_64/lib/libfreetype.a +0 -0
  168. data/assets/windows/mingw-w64-x86_64/lib/libglew32.a +0 -0
  169. data/assets/windows/mingw-w64-x86_64/lib/libharfbuzz.a +0 -0
  170. data/assets/windows/mingw-w64-x86_64/lib/libhwy.a +0 -0
  171. data/assets/windows/mingw-w64-x86_64/lib/libjpeg.a +0 -0
  172. data/assets/windows/mingw-w64-x86_64/lib/libjxl.a +0 -0
  173. data/assets/windows/mingw-w64-x86_64/lib/liblzma.a +0 -0
  174. data/assets/windows/mingw-w64-x86_64/lib/libmpg123.a +0 -0
  175. data/assets/windows/mingw-w64-x86_64/lib/libmruby.a +0 -0
  176. data/assets/windows/mingw-w64-x86_64/lib/libopus.a +0 -0
  177. data/assets/windows/mingw-w64-x86_64/lib/libpng.a +0 -0
  178. data/assets/windows/mingw-w64-x86_64/lib/libsndfile.a +0 -0
  179. data/assets/windows/mingw-w64-x86_64/lib/libssp.a +0 -0
  180. data/assets/windows/mingw-w64-x86_64/lib/libstdc++.a +0 -0
  181. data/assets/windows/mingw-w64-x86_64/lib/libtiff.a +0 -0
  182. data/assets/windows/mingw-w64-x86_64/lib/libwebp.a +0 -0
  183. data/assets/windows/mingw-w64-x86_64/lib/libz.a +0 -0
  184. data/assets/windows/mingw-w64-x86_64/lib/libzstd.a +0 -0
  185. data/ext/ruby2d/canvas.c +540 -0
  186. data/ext/ruby2d/extconf.rb +39 -21
  187. data/ext/ruby2d/gl.c +3 -3
  188. data/ext/ruby2d/image.c +7 -7
  189. data/ext/ruby2d/ruby2d.c +741 -24
  190. data/ext/ruby2d/ruby2d.h +66 -3
  191. data/ext/ruby2d/sound.c +16 -2
  192. data/lib/ruby2d/canvas.rb +315 -0
  193. data/lib/ruby2d/circle.rb +30 -15
  194. data/lib/ruby2d/cli/build.rb +11 -4
  195. data/lib/ruby2d/cli/enable_console.rb +3 -1
  196. data/lib/ruby2d/color.rb +133 -77
  197. data/lib/ruby2d/core.rb +32 -0
  198. data/lib/ruby2d/dsl.rb +38 -32
  199. data/lib/ruby2d/exceptions.rb +2 -1
  200. data/lib/ruby2d/font.rb +97 -62
  201. data/lib/ruby2d/image.rb +48 -27
  202. data/lib/ruby2d/line.rb +84 -45
  203. data/lib/ruby2d/music.rb +33 -23
  204. data/lib/ruby2d/pixel.rb +10 -9
  205. data/lib/ruby2d/pixmap.rb +39 -0
  206. data/lib/ruby2d/pixmap_atlas.rb +56 -0
  207. data/lib/ruby2d/quad.rb +98 -49
  208. data/lib/ruby2d/rectangle.rb +35 -36
  209. data/lib/ruby2d/renderable.rb +7 -6
  210. data/lib/ruby2d/sound.rb +23 -17
  211. data/lib/ruby2d/sprite.rb +181 -140
  212. data/lib/ruby2d/square.rb +21 -20
  213. data/lib/ruby2d/text.rb +47 -19
  214. data/lib/ruby2d/texture.rb +13 -3
  215. data/lib/ruby2d/tileset.rb +97 -44
  216. data/lib/ruby2d/triangle.rb +91 -42
  217. data/lib/ruby2d/version.rb +3 -1
  218. data/lib/ruby2d/vertices.rb +81 -45
  219. data/lib/ruby2d/window.rb +508 -371
  220. data/lib/ruby2d.rb +11 -29
  221. metadata +84 -16
  222. data/assets/include/SDL2/SDL_config_psp.h +0 -165
  223. data/assets/include/SDL2/SDL_config_wiz.h +0 -154
  224. data/assets/include/glew.h +0 -23686
  225. data/assets/macos/universal/lib/libpng16.a +0 -0
  226. data/assets/wasm/build_config.rb +0 -13
  227. data/assets/windows/glew/README.md +0 -10
  228. data/assets/windows/glew/glew.h +0 -23686
  229. data/assets/windows/glew/libglew32.a +0 -0
  230. data/assets/windows/mingw-w64-x86_64/lib/libpng16.a +0 -0
  231. data/lib/ruby2d/entity.rb +0 -17
data/ext/ruby2d/ruby2d.c CHANGED
@@ -90,6 +90,7 @@
90
90
  #define r_ary_entry(ary, pos) rb_ary_entry(ary, pos)
91
91
  #define r_ary_new() rb_ary_new()
92
92
  #define r_ary_push(self, val) rb_ary_push(self, val)
93
+ #define r_ary_len(self) rb_ary_len(self)
93
94
  #define r_data_wrap_struct(name, data) Data_Wrap_Struct(rb_cObject, NULL, (free_##name), data)
94
95
  #define r_data_get_struct(self, var, mrb_type, rb_type, data) Data_Get_Struct(r_iv_get(self, var), rb_type, data)
95
96
  #define r_define_module(name) rb_define_module(name)
@@ -132,11 +133,21 @@ static void free_surface(mrb_state *mrb, void *p_);
132
133
  static const struct mrb_data_type surface_data_type = {
133
134
  "surface", free_surface
134
135
  };
136
+ static void free_sdl_texture(mrb_state *mrb, void *p_);
137
+ static const struct mrb_data_type sdl_texture_data_type = {
138
+ "sdl_texture", free_sdl_texture
139
+ };
140
+ static void free_renderer(mrb_state *mrb, void *p_);
141
+ static const struct mrb_data_type renderer_data_type = {
142
+ "renderer", free_renderer
143
+ };
135
144
  #else
136
145
  static void free_sound(R2D_Sound *snd);
137
146
  static void free_music(R2D_Music *mus);
138
147
  static void free_font(TTF_Font *font);
139
148
  static void free_surface(SDL_Surface *surface);
149
+ static void free_sdl_texture(SDL_Texture *surface);
150
+ static void free_renderer(SDL_Renderer *renderer);
140
151
  #endif
141
152
 
142
153
 
@@ -371,31 +382,46 @@ static R_VAL ruby2d_circle_ext_draw(R_VAL self, R_VAL a) {
371
382
 
372
383
 
373
384
  /*
374
- * Ruby2D::Image#ext_load_image
375
- * Create an SDL surface from an image path, return the surface, width, and height
385
+ * Ruby2D::Pixmap#ext_load_pixmap
386
+ * Create an SDL surface from an image path, and ...
387
+ * TODO: store the surface, width, and height in the object
376
388
  */
377
389
  #if MRUBY
378
- static R_VAL ruby2d_image_ext_load_image(mrb_state* mrb, R_VAL self) {
390
+ static R_VAL ruby2d_pixmap_ext_load_pixmap(mrb_state* mrb, R_VAL self) {
379
391
  mrb_value path;
380
392
  mrb_get_args(mrb, "o", &path);
381
393
  #else
382
- static R_VAL ruby2d_image_ext_load_image(R_VAL self, R_VAL path) {
394
+ static R_VAL ruby2d_pixmap_ext_load_pixmap(R_VAL self, R_VAL path) {
383
395
  #endif
384
396
  R2D_Init();
385
397
 
386
- R_VAL result = r_ary_new();
387
-
388
398
  SDL_Surface *surface = R2D_CreateImageSurface(RSTRING_PTR(path));
389
- R2D_ImageConvertToRGB(surface);
390
-
391
- r_ary_push(result, r_data_wrap_struct(surface, surface));
392
- r_ary_push(result, INT2NUM(surface->w));
393
- r_ary_push(result, INT2NUM(surface->h));
399
+ // initialize for later use
400
+ r_iv_set(self, "@ext_sdl_texture", R_NIL);
401
+
402
+ if (surface != NULL) {
403
+ #if GLES
404
+ // OpenGL ES doesn't support BGR color order, so applying the
405
+ // conversion to the pixels. This will however render incorrect colours
406
+ // for BGR images when using Canvas.
407
+ // TODO: A better solution one day?
408
+ R2D_ImageConvertToRGB(surface);
409
+ #endif
394
410
 
395
- return result;
411
+ r_iv_set(self, "@ext_pixel_data", r_data_wrap_struct(surface, surface));
412
+ r_iv_set(self, "@width", INT2NUM(surface->w));
413
+ r_iv_set(self, "@height", INT2NUM(surface->h));
414
+ }
415
+ else {
416
+ // TODO: consider raising an exception?
417
+ // for docs: https://silverhammermba.github.io/emberb/c/#raise
418
+ r_iv_set(self, "@ext_pixel_data", R_NIL);
419
+ r_iv_set(self, "@width", INT2NUM(0));
420
+ r_iv_set(self, "@height", INT2NUM(0));
421
+ }
422
+ return R_NIL;
396
423
  }
397
424
 
398
-
399
425
  /*
400
426
  * Ruby2D::Text#ext_load_text
401
427
  */
@@ -430,6 +456,69 @@ static R_VAL ruby2d_text_ext_load_text(R_VAL self, R_VAL font, R_VAL message) {
430
456
  return result;
431
457
  }
432
458
 
459
+ /*
460
+ * Ruby2D::Canvas#ext_draw_pixmap
461
+ */
462
+ #if MRUBY
463
+ static R_VAL ruby2d_canvas_ext_draw_pixmap(mrb_state* mrb, R_VAL self) {
464
+ mrb_value pixmap, src_rect, x, y, w, h;
465
+ mrb_get_args(mrb, "oooooo", &pixmap, &src_rect, &x, &y, &w, &h);
466
+ #else
467
+ static R_VAL ruby2d_canvas_ext_draw_pixmap(R_VAL self, R_VAL pixmap, R_VAL src_rect, R_VAL x, R_VAL y, R_VAL w, R_VAL h) {
468
+ #endif
469
+
470
+ if (r_test(pixmap)) {
471
+ // Retrieve pixmap's external pixel data (SDL_Surface)
472
+ SDL_Surface *pix_surface;
473
+ r_data_get_struct(pixmap, "@ext_pixel_data", &surface_data_type, SDL_Surface, pix_surface);
474
+
475
+ SDL_Texture *pix_sdl_tex = NULL;
476
+ R_VAL pix_ext_sdl_tex = r_iv_get(pixmap, "@ext_sdl_texture");
477
+ if (r_test(pix_ext_sdl_tex)) {
478
+ r_data_get_struct(pixmap, "@ext_sdl_texture", &sdl_texture_data_type, SDL_Texture, pix_sdl_tex);
479
+ }
480
+
481
+ SDL_Renderer *render;
482
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
483
+
484
+ if (pix_sdl_tex == NULL) {
485
+ // create and cache an SDL_Texture for this Pixmap
486
+ pix_sdl_tex = SDL_CreateTextureFromSurface(render, pix_surface);
487
+ if (pix_sdl_tex != NULL) {
488
+ r_iv_set(pixmap, "@ext_sdl_texture", r_data_wrap_struct(sdl_texture, pix_sdl_tex));
489
+ }
490
+ else printf("*** Unable to create SDL_Texture: %s\n", SDL_GetError());
491
+ }
492
+
493
+ // Draw if we have an SDL_Texture
494
+ if (pix_sdl_tex != NULL) {
495
+ SDL_bool src_set = SDL_FALSE;
496
+ SDL_Rect src;
497
+ if (r_test(src_rect)) {
498
+ src_set = SDL_TRUE;
499
+ // portion of pixmap
500
+ src = (SDL_Rect) {
501
+ .x = NUM2INT(r_ary_entry(src_rect, 0)),
502
+ .y = NUM2INT(r_ary_entry(src_rect, 1)),
503
+ .w = NUM2INT(r_ary_entry(src_rect, 2)),
504
+ .h = NUM2INT(r_ary_entry(src_rect, 3))
505
+ };
506
+ }
507
+ else {
508
+ // whole pixmap
509
+ src = (SDL_Rect){ .x = 0, .y = 0, .w = pix_surface->w, .h = pix_surface->h };
510
+ }
511
+ // use incoming size or source size or fallback to pixmap size
512
+ int pix_w = r_test(w) ? NUM2INT(w) : (src_set ? src.w : NUM2INT(r_iv_get(pixmap, "@width")));
513
+ int pix_h = r_test(h) ? NUM2INT(h) : (src_set ? src.h : NUM2INT(r_iv_get(pixmap, "@height")));
514
+
515
+ SDL_Rect dst = { .x = NUM2INT(x), .y = NUM2INT(y), .w = pix_w, .h = pix_h };
516
+ SDL_RenderCopy (render, pix_sdl_tex, &src, &dst);
517
+ }
518
+ }
519
+ return R_NIL;
520
+ }
521
+
433
522
 
434
523
  /*
435
524
  * Ruby2D::Texture#ext_create
@@ -451,19 +540,47 @@ static R_VAL ruby2d_texture_ext_create(R_VAL self, R_VAL rubySurface, R_VAL widt
451
540
  #endif
452
541
 
453
542
  // Detect image mode
454
- GLint format = GL_RGB;
455
- if (surface->format->BytesPerPixel == 4) {
456
- format = GL_RGBA;
457
- }
543
+ GLint gl_internal_format, gl_format;
544
+ GLenum gl_type;
458
545
 
459
- R2D_GL_CreateTexture(&texture_id, format,
546
+ switch (surface->format->BytesPerPixel) {
547
+ case 4:
548
+ #if GLES
549
+ gl_internal_format = gl_format = GL_RGBA;
550
+ #else
551
+ gl_internal_format = GL_RGBA;
552
+ gl_format = (surface->format->Rmask == 0xff0000) ? GL_BGRA : GL_RGBA;
553
+ #endif
554
+ gl_type = GL_UNSIGNED_BYTE;
555
+ break;
556
+ case 3:
557
+ #if GLES
558
+ gl_internal_format = gl_format = GL_RGB;
559
+ #else
560
+ gl_internal_format = GL_RGB;
561
+ gl_format = (surface->format->Rmask == 0xff0000) ? GL_BGR : GL_RGB;
562
+ #endif
563
+ gl_type = GL_UNSIGNED_BYTE;
564
+ break;
565
+ case 2:
566
+ gl_internal_format = gl_format = GL_RGB;
567
+ gl_type = GL_UNSIGNED_SHORT_5_6_5;
568
+ break;
569
+ case 1:
570
+ default:
571
+ // this would be ideal for font glyphs which use luminance + alpha and colour
572
+ // is set when drawing
573
+ gl_internal_format = gl_format = GL_LUMINANCE_ALPHA;
574
+ gl_type = GL_UNSIGNED_BYTE;
575
+ break;
576
+ }
577
+ R2D_GL_CreateTexture(&texture_id, gl_internal_format, gl_format, gl_type,
460
578
  NUM2INT(width), NUM2INT(height),
461
579
  surface->pixels, GL_NEAREST);
462
580
 
463
581
  return INT2NUM(texture_id);
464
582
  }
465
583
 
466
-
467
584
  /*
468
585
  * Ruby2D::Texture#ext_delete
469
586
  */
@@ -482,6 +599,528 @@ static R_VAL ruby2d_texture_ext_delete(R_VAL self, R_VAL rubyTexture_id) {
482
599
  }
483
600
 
484
601
 
602
+ /*
603
+ * Ruby2D::Canvas#ext_create
604
+ */
605
+ #if MRUBY
606
+ static R_VAL ruby2d_canvas_ext_create(mrb_state* mrb, R_VAL self) {
607
+ mrb_value a;
608
+ mrb_get_args(mrb, "o", &a);
609
+ #else
610
+ static R_VAL ruby2d_canvas_ext_create(R_VAL self, R_VAL a) {
611
+ #endif
612
+ SDL_Surface *surf = SDL_CreateRGBSurface(
613
+ 0, NUM2INT(r_ary_entry(a, 0)), NUM2INT(r_ary_entry(a, 1)),
614
+ 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
615
+ );
616
+
617
+ SDL_Renderer *render = SDL_CreateSoftwareRenderer(surf);
618
+
619
+ SDL_SetRenderDrawColor(render,
620
+ NUM2DBL(r_ary_entry(a, 2)) * 255, // r
621
+ NUM2DBL(r_ary_entry(a, 3)) * 255, // g
622
+ NUM2DBL(r_ary_entry(a, 4)) * 255, // b
623
+ NUM2DBL(r_ary_entry(a, 5)) * 255 // a
624
+ );
625
+ SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_NONE);
626
+ SDL_RenderClear(render);
627
+
628
+ SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_BLEND);
629
+ SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_BLEND);
630
+
631
+ r_iv_set(self, "@ext_pixel_data", r_data_wrap_struct(surface, surf));
632
+ r_iv_set(self, "@ext_renderer", r_data_wrap_struct(renderer, render));
633
+ return R_NIL;
634
+ }
635
+
636
+ /*
637
+ * Ruby2D::Canvas#ext_clear
638
+ */
639
+ #if MRUBY
640
+ static R_VAL ruby2d_canvas_ext_clear(mrb_state* mrb, R_VAL self) {
641
+ mrb_value a;
642
+ mrb_get_args(mrb, "o", &a);
643
+ #else
644
+ static R_VAL ruby2d_canvas_ext_clear(R_VAL self, R_VAL a) {
645
+ #endif
646
+ // `a` is the array representing the colour values
647
+
648
+ SDL_Renderer *render;
649
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
650
+
651
+ SDL_SetRenderDrawColor(render,
652
+ NUM2DBL(r_ary_entry(a, 0)) * 255, // r
653
+ NUM2DBL(r_ary_entry(a, 1)) * 255, // g
654
+ NUM2DBL(r_ary_entry(a, 2)) * 255, // b
655
+ NUM2DBL(r_ary_entry(a, 3)) * 255 // a
656
+ );
657
+ SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_NONE);
658
+ SDL_RenderClear(render);
659
+ SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_BLEND);
660
+
661
+ return R_NIL;
662
+ }
663
+
664
+ /*
665
+ * Ruby2D::Canvas#ext_fill_rectangle
666
+ */
667
+ #if MRUBY
668
+ static R_VAL ruby2d_canvas_ext_fill_rectangle(mrb_state* mrb, R_VAL self) {
669
+ mrb_value a;
670
+ mrb_get_args(mrb, "o", &a);
671
+ #else
672
+ static R_VAL ruby2d_canvas_ext_fill_rectangle(R_VAL self, R_VAL a) {
673
+ #endif
674
+ // `a` is the array representing the rectangle
675
+
676
+ SDL_Renderer *render;
677
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
678
+
679
+ SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_BLEND);
680
+
681
+ SDL_Rect rect = { .x = NUM2INT(r_ary_entry(a, 0)),
682
+ .y = NUM2INT(r_ary_entry(a, 1)),
683
+ .w = NUM2INT(r_ary_entry(a, 2)),
684
+ .h = NUM2INT(r_ary_entry(a, 3))
685
+ };
686
+
687
+ SDL_SetRenderDrawColor(render,
688
+ NUM2DBL(r_ary_entry(a, 4)) * 255, // r
689
+ NUM2DBL(r_ary_entry(a, 5)) * 255, // g
690
+ NUM2DBL(r_ary_entry(a, 6)) * 255, // b
691
+ NUM2DBL(r_ary_entry(a, 7)) * 255 // a
692
+ );
693
+ SDL_RenderFillRect(render, &rect);
694
+
695
+ return R_NIL;
696
+ }
697
+
698
+ /*
699
+ * Ruby2D::Canvas#ext_draw_rectangle
700
+ */
701
+ #if MRUBY
702
+ static R_VAL ruby2d_canvas_ext_draw_rectangle(mrb_state* mrb, R_VAL self) {
703
+ mrb_value a;
704
+ mrb_get_args(mrb, "o", &a);
705
+ #else
706
+ static R_VAL ruby2d_canvas_ext_draw_rectangle(R_VAL self, R_VAL a) {
707
+ #endif
708
+ // `a` is the array representing the rectangle
709
+ // 0, 1, 2, 3, 4, 5, 6, 7, 8
710
+ // [ x, y, width, height, thickness, r, g, b, a]
711
+
712
+ SDL_Renderer *render;
713
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
714
+
715
+ int thickness = NUM2INT(r_ary_entry(a, 4));
716
+ if (thickness == 1) {
717
+ SDL_Rect rect = { .x = NUM2INT(r_ary_entry(a, 0)),
718
+ .y = NUM2INT(r_ary_entry(a, 1)),
719
+ .w = NUM2INT(r_ary_entry(a, 2)),
720
+ .h = NUM2INT(r_ary_entry(a, 3))
721
+ };
722
+
723
+ SDL_SetRenderDrawColor(render,
724
+ NUM2DBL(r_ary_entry(a, 5)) * 255, // r
725
+ NUM2DBL(r_ary_entry(a, 6)) * 255, // g
726
+ NUM2DBL(r_ary_entry(a, 7)) * 255, // b
727
+ NUM2DBL(r_ary_entry(a, 8)) * 255 // a
728
+ );
729
+ SDL_RenderDrawRect(render, &rect);
730
+ }
731
+ else if (thickness > 1) {
732
+ R2D_Canvas_DrawThickRect(render,
733
+ NUM2INT(r_ary_entry(a, 0)), // x
734
+ NUM2INT(r_ary_entry(a, 1)), // y
735
+ NUM2INT(r_ary_entry(a, 2)), // width
736
+ NUM2INT(r_ary_entry(a, 3)), // height
737
+ thickness,
738
+ NUM2DBL(r_ary_entry(a, 5)) * 255, // r
739
+ NUM2DBL(r_ary_entry(a, 6)) * 255, // g
740
+ NUM2DBL(r_ary_entry(a, 7)) * 255, // b
741
+ NUM2DBL(r_ary_entry(a, 8)) * 255 // a
742
+ );
743
+ }
744
+ return R_NIL;
745
+ }
746
+
747
+ /*
748
+ * Ruby2D::Canvas#ext_draw_line
749
+ */
750
+ #if MRUBY
751
+ static R_VAL ruby2d_canvas_ext_draw_line(mrb_state* mrb, R_VAL self) {
752
+ mrb_value a;
753
+ mrb_get_args(mrb, "o", &a);
754
+ #else
755
+ static R_VAL ruby2d_canvas_ext_draw_line(R_VAL self, R_VAL a) {
756
+ #endif
757
+ // `a` is the array representing the line
758
+
759
+ SDL_Renderer *render;
760
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
761
+
762
+ int thickness = NUM2INT(r_ary_entry(a, 4));
763
+ if (thickness == 1) {
764
+ // use the SDL_Renderer's draw line for single pixel lines
765
+ SDL_SetRenderDrawColor(render,
766
+ NUM2DBL(r_ary_entry(a, 5)) * 255, // r
767
+ NUM2DBL(r_ary_entry(a, 6)) * 255, // g
768
+ NUM2DBL(r_ary_entry(a, 7)) * 255, // b
769
+ NUM2DBL(r_ary_entry(a, 8)) * 255 // a
770
+ );
771
+ SDL_RenderDrawLine(render,
772
+ NUM2INT(r_ary_entry(a, 0)), // x1
773
+ NUM2INT(r_ary_entry(a, 1)), // y1
774
+ NUM2INT(r_ary_entry(a, 2)), // x2
775
+ NUM2INT(r_ary_entry(a, 3)) // y2
776
+ );
777
+ }
778
+ else if (thickness > 1) {
779
+ // use a custom handler to convert a thick line into a
780
+ // quad and draw using SDL_Renderer's geometry renderer
781
+ R2D_Canvas_DrawThickLine(render,
782
+ NUM2INT(r_ary_entry(a, 0)), // x1
783
+ NUM2INT(r_ary_entry(a, 1)), // y1
784
+ NUM2INT(r_ary_entry(a, 2)), // x2
785
+ NUM2INT(r_ary_entry(a, 3)), // y2
786
+ thickness,
787
+ NUM2DBL(r_ary_entry(a, 5)) * 255, // r
788
+ NUM2DBL(r_ary_entry(a, 6)) * 255, // g
789
+ NUM2DBL(r_ary_entry(a, 7)) * 255, // b
790
+ NUM2DBL(r_ary_entry(a, 8)) * 255 // a
791
+ );
792
+ }
793
+
794
+ return R_NIL;
795
+ }
796
+
797
+ #define MAX_POLY_POINTS 64
798
+
799
+ /*
800
+ * Ruby2D::Canvas#ext_draw_polyline
801
+ */
802
+ #if MRUBY
803
+ static R_VAL ruby2d_canvas_ext_draw_polyline(mrb_state* mrb, R_VAL self) {
804
+ mrb_value config, coords;
805
+ mrb_get_args(mrb, "oo", &config, &coords);
806
+ #else
807
+ static R_VAL ruby2d_canvas_ext_draw_polyline(R_VAL self, R_VAL config, R_VAL coords) {
808
+ #endif
809
+ // `config` is an array
810
+ // 0, 1, 2, 3, 4
811
+ // [ thickness, r, g, b, a ]
812
+ //
813
+ // `coords` is an array of x, y values
814
+ // 0, 1, 2, 3, ...
815
+ // [ x1, y1, x2, y2, ... ]
816
+
817
+ SDL_Renderer *render;
818
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
819
+
820
+ long coord_count = RARRAY_LEN(coords);
821
+ int thickness = NUM2INT(r_ary_entry(config, 0));
822
+ if (thickness == 1) {
823
+ // use the SDL_Renderer's draw line for single pixel lines
824
+ SDL_SetRenderDrawColor(render,
825
+ NUM2DBL(r_ary_entry(config, 1)) * 255, // r
826
+ NUM2DBL(r_ary_entry(config, 2)) * 255, // g
827
+ NUM2DBL(r_ary_entry(config, 3)) * 255, // b
828
+ NUM2DBL(r_ary_entry(config, 4)) * 255 // a
829
+ );
830
+ int x1 = NUM2INT(r_ary_entry(coords, 0));
831
+ int y1 = NUM2INT(r_ary_entry(coords, 1));
832
+ for (int i = 2; i < coord_count; i+= 2) {
833
+ int x2 = NUM2INT(r_ary_entry(coords, i));
834
+ int y2 = NUM2INT(r_ary_entry(coords, i+1));
835
+ SDL_RenderDrawLine(render, x1, y1, x2, y2);
836
+ x1 = x2;
837
+ y1 = y2;
838
+ }
839
+ }
840
+ else if (thickness > 1) {
841
+ // use a custom handler to convert a thick line into a
842
+ // quad and draw using SDL_Renderer's geometry renderer
843
+
844
+ SDL_FPoint points[MAX_POLY_POINTS];
845
+ int num_points = 0;
846
+
847
+ points[num_points++] = (SDL_FPoint) {
848
+ .x = NUM2INT(r_ary_entry(coords, 0)),
849
+ .y = NUM2INT(r_ary_entry(coords, 1))
850
+ };
851
+ for (int i = 2; i < coord_count && num_points < MAX_POLY_POINTS; i+= 2) {
852
+ points[num_points++] = (SDL_FPoint) {
853
+ .x = NUM2INT(r_ary_entry(coords, i)),
854
+ .y = NUM2INT(r_ary_entry(coords, i+1)) };
855
+ }
856
+ R2D_Canvas_DrawThickPolyline(render,
857
+ points, num_points,
858
+ thickness,
859
+ NUM2DBL(r_ary_entry(config, 1)) * 255, // r
860
+ NUM2DBL(r_ary_entry(config, 2)) * 255, // g
861
+ NUM2DBL(r_ary_entry(config, 3)) * 255, // b
862
+ NUM2DBL(r_ary_entry(config, 4)) * 255, // a
863
+ false // don't skip first/last
864
+ );
865
+ }
866
+
867
+ return R_NIL;
868
+ }
869
+
870
+ /*
871
+ * Ruby2D::Canvas#ext_draw_polygon
872
+ */
873
+ #if MRUBY
874
+ static R_VAL ruby2d_canvas_ext_draw_polygon(mrb_state* mrb, R_VAL self) {
875
+ mrb_value config, coords;
876
+ mrb_get_args(mrb, "oo", &config, &coords);
877
+ #else
878
+ static R_VAL ruby2d_canvas_ext_draw_polygon(R_VAL self, R_VAL config, R_VAL coords) {
879
+ #endif
880
+ // `config` is an array
881
+ // 0, 1, 2, 3, 4
882
+ // [ thickness, r, g, b, a ]
883
+ //
884
+ // `coords` is an array of x, y values
885
+ // 0, 1, 2, 3, ...
886
+ // [ x1, y1, x2, y2, ... ]
887
+
888
+ SDL_Renderer *render;
889
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
890
+
891
+ long coord_count = RARRAY_LEN(coords);
892
+ int thickness = NUM2INT(r_ary_entry(config, 0));
893
+ if (thickness == 1) {
894
+ // use the SDL_Renderer's draw line for single pixel lines
895
+ SDL_SetRenderDrawColor(render,
896
+ NUM2DBL(r_ary_entry(config, 1)) * 255, // r
897
+ NUM2DBL(r_ary_entry(config, 2)) * 255, // g
898
+ NUM2DBL(r_ary_entry(config, 3)) * 255, // b
899
+ NUM2DBL(r_ary_entry(config, 4)) * 255 // a
900
+ );
901
+ int x1 = NUM2INT(r_ary_entry(coords, 0));
902
+ int y1 = NUM2INT(r_ary_entry(coords, 1));
903
+ for (int i = 2; i < coord_count; i+= 2) {
904
+ int x2 = NUM2INT(r_ary_entry(coords, i));
905
+ int y2 = NUM2INT(r_ary_entry(coords, i+1));
906
+ SDL_RenderDrawLine(render, x1, y1, x2, y2);
907
+ x1 = x2;
908
+ y1 = y2;
909
+ }
910
+ // connect back to first point to close the shape
911
+ int x2 = NUM2INT(r_ary_entry(coords, 0));
912
+ int y2 = NUM2INT(r_ary_entry(coords, 1));
913
+ SDL_RenderDrawLine(render, x1, y1, x2, y2);
914
+ }
915
+ else if (thickness > 1) {
916
+ // use a custom handler to convert a thick line into a
917
+ // quad and draw using SDL_Renderer's geometry renderer
918
+
919
+ SDL_FPoint points[MAX_POLY_POINTS+3]; // three extra slots to points 0, 1, 2
920
+ int num_points = 0;
921
+
922
+ points[num_points++] = (SDL_FPoint) {
923
+ .x = NUM2INT(r_ary_entry(coords, 0)),
924
+ .y = NUM2INT(r_ary_entry(coords, 1))
925
+ };
926
+ for (int i = 2; i < coord_count && num_points < MAX_POLY_POINTS; i+= 2) {
927
+ points[num_points++] = (SDL_FPoint) {
928
+ .x = NUM2INT(r_ary_entry(coords, i)),
929
+ .y = NUM2INT(r_ary_entry(coords, i+1)) };
930
+ }
931
+ // repeat first three coordinates at the end
932
+ points[num_points++] = points[0];
933
+ points[num_points++] = points[1];
934
+ points[num_points++] = points[2];
935
+ // use polyline draw but ask it to skip first and last segments
936
+ // since we added three more points at the end, these produce the
937
+ // missing segments with proper joins
938
+ R2D_Canvas_DrawThickPolyline(render,
939
+ points, num_points,
940
+ thickness,
941
+ NUM2DBL(r_ary_entry(config, 1)) * 255, // r
942
+ NUM2DBL(r_ary_entry(config, 2)) * 255, // g
943
+ NUM2DBL(r_ary_entry(config, 3)) * 255, // b
944
+ NUM2DBL(r_ary_entry(config, 4)) * 255, // a
945
+ true // skip first/last segments when drawing the polyline
946
+ );
947
+ }
948
+
949
+ return R_NIL;
950
+ }
951
+
952
+ /*
953
+ * Ruby2D::Canvas#ext_fill_polygon
954
+ */
955
+ #if MRUBY
956
+ static R_VAL ruby2d_canvas_ext_fill_polygon(mrb_state* mrb, R_VAL self) {
957
+ mrb_value coords, rgbas;
958
+ mrb_get_args(mrb, "oo", &coords, &rgbas);
959
+ #else
960
+ static R_VAL ruby2d_canvas_ext_fill_polygon(R_VAL self, R_VAL coords, R_VAL rgbas) {
961
+ #endif
962
+ // `coords` is an array of x, y values
963
+ // 0, 1, 2, 3, ...
964
+ // [ x1, y1, x2, y2, ... ]
965
+ //
966
+ // `rgbas` is an array of r, g, b, a values
967
+ // 0, 1, 2, 3, 4, 5, 6, 7 ...
968
+ // [ r1, g1, b1, a1, r2, g2, b2, a2, ... ]
969
+
970
+ SDL_Renderer *render;
971
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
972
+
973
+ long coord_len = RARRAY_LEN(coords);
974
+ long rgbas_len = RARRAY_LEN(rgbas);
975
+
976
+ if (coord_len >= 6 && rgbas_len > 0) {
977
+ SDL_FPoint points[MAX_POLY_POINTS];
978
+ int num_points = 0;
979
+
980
+ SDL_Color colors[MAX_POLY_POINTS];
981
+ int num_colors = 0;
982
+
983
+ for (int i = 0; i < coord_len && num_points < MAX_POLY_POINTS; i+= 2) {
984
+ points[num_points++] = (SDL_FPoint) {
985
+ .x = NUM2INT(r_ary_entry(coords, i)),
986
+ .y = NUM2INT(r_ary_entry(coords, i+1)) };
987
+ }
988
+ for (int i = 0; i < rgbas_len && num_colors < MAX_POLY_POINTS; i+= 4) {
989
+ colors[num_colors++] = (SDL_Color) {
990
+ .r = NUM2DBL(r_ary_entry(rgbas, i)) * 255, // r
991
+ .g = NUM2DBL(r_ary_entry(rgbas, i+1)) * 255, // g
992
+ .b = NUM2DBL(r_ary_entry(rgbas, i+2)) * 255, // b
993
+ .a = NUM2DBL(r_ary_entry(rgbas, i+3)) * 255 // a
994
+ };
995
+ }
996
+
997
+ R2D_Canvas_FillPolygon(render, points, num_points, colors, num_colors);
998
+ }
999
+
1000
+ return R_NIL;
1001
+ }
1002
+
1003
+ /*
1004
+ * Ruby2D::Canvas#self.ext_fill_ellipse
1005
+ */
1006
+ #if MRUBY
1007
+ static R_VAL ruby2d_canvas_ext_fill_ellipse(mrb_state* mrb, R_VAL self) {
1008
+ mrb_value a;
1009
+ mrb_get_args(mrb, "o", &a);
1010
+ #else
1011
+ static R_VAL ruby2d_canvas_ext_fill_ellipse(R_VAL self, R_VAL a) {
1012
+ #endif
1013
+ // `a` is the array representing the filled circle
1014
+ // 0 1 2 3 4 5 6 7 8
1015
+ // [ x, y, xradius, yradius, sectors, r, g, b, a ]
1016
+ SDL_Renderer *render;
1017
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
1018
+
1019
+ SDL_Vertex verts[3];
1020
+ // center
1021
+ float x, y;
1022
+ verts[0].position = (SDL_FPoint) {
1023
+ .x = x = NUM2INT(r_ary_entry(a, 0)),
1024
+ .y = y = NUM2INT(r_ary_entry(a, 1))
1025
+ };
1026
+ // dimensions
1027
+ float xradius = NUM2INT(r_ary_entry(a, 2));
1028
+ float yradius = NUM2INT(r_ary_entry(a, 3));
1029
+ float sectors = NUM2INT(r_ary_entry(a, 4));
1030
+ float unit_angle = 2 * M_PI / sectors;
1031
+
1032
+ // colour all vertices
1033
+ verts[1].color = verts[2].color = verts[0].color = (SDL_Color) {
1034
+ .r = NUM2DBL(r_ary_entry(a, 5)) * 255,
1035
+ .g = NUM2DBL(r_ary_entry(a, 6)) * 255,
1036
+ .b = NUM2DBL(r_ary_entry(a, 7)) * 255,
1037
+ .a = NUM2DBL(r_ary_entry(a, 8)) * 255,
1038
+ };
1039
+
1040
+ // point at 0 radians
1041
+ verts[1].position = (SDL_FPoint) {
1042
+ .x = x + xradius * cosf(0),
1043
+ .y = y + yradius * sinf(0)
1044
+ };
1045
+ for (float i = 1; i <= sectors; i++) {
1046
+ float angle = i * unit_angle;
1047
+ // re-use from previous calculation
1048
+ verts[2].position = verts[1].position;
1049
+ // calculate new point
1050
+ verts[1].position = (SDL_FPoint) {
1051
+ .x = x + xradius * cosf(angle),
1052
+ .y = y + yradius * sinf(angle)
1053
+ };
1054
+ SDL_RenderGeometry(render, NULL, verts, 3, NULL, 0);
1055
+ }
1056
+
1057
+ return R_NIL;
1058
+ }
1059
+
1060
+ /*
1061
+ * Ruby2D::Canvas#self.ext_draw_ellipse
1062
+ */
1063
+ #if MRUBY
1064
+ static R_VAL ruby2d_canvas_ext_draw_ellipse(mrb_state* mrb, R_VAL self) {
1065
+ mrb_value a;
1066
+ mrb_get_args(mrb, "o", &a);
1067
+ #else
1068
+ static R_VAL ruby2d_canvas_ext_draw_ellipse(R_VAL self, R_VAL a) {
1069
+ #endif
1070
+ // `a` is the array representing the ellipse to draw
1071
+ // 0 1 2 3 4 5 6 7 8 9
1072
+ // [ x, y, xradius, yradius, sectors, thickness, r, g, b, a ]
1073
+
1074
+ // thickness
1075
+ int thickness = NUM2INT(r_ary_entry(a, 5));
1076
+ if (thickness <= 0) return R_NIL;
1077
+
1078
+ SDL_Renderer *render;
1079
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
1080
+
1081
+ // center
1082
+ float x = NUM2INT(r_ary_entry(a, 0));
1083
+ float y = NUM2INT(r_ary_entry(a, 1)) ;
1084
+ // dimensions
1085
+ float xradius = NUM2INT(r_ary_entry(a, 2));
1086
+ float yradius = NUM2INT(r_ary_entry(a, 3));
1087
+ float sectors = NUM2INT(r_ary_entry(a, 4));
1088
+ // colors
1089
+ int clr_r = NUM2DBL(r_ary_entry(a, 6)) * 255;
1090
+ int clr_g = NUM2DBL(r_ary_entry(a, 7)) * 255;
1091
+ int clr_b = NUM2DBL(r_ary_entry(a, 8)) * 255;
1092
+ int clr_a = NUM2DBL(r_ary_entry(a, 9)) * 255;
1093
+
1094
+ if (thickness > 1) {
1095
+ R2D_Canvas_DrawThickEllipse(render,
1096
+ x, y, xradius, yradius, sectors, thickness,
1097
+ clr_r, clr_g, clr_b, clr_a);
1098
+ }
1099
+ else {
1100
+ R2D_Canvas_DrawThinEllipse(render,
1101
+ x, y, xradius, yradius, sectors,
1102
+ clr_r, clr_g, clr_b, clr_a);
1103
+ }
1104
+
1105
+ return R_NIL;
1106
+ }
1107
+
1108
+ /*
1109
+ * Calculate the cross product of the two lines
1110
+ * connecting the three points clock-wise. A negative value
1111
+ * means the angle "to the right" is > 180.
1112
+ */
1113
+ /* Unused
1114
+ static inline int cross_product_corner(x1, y1, x2, y2, x3, y3) {
1115
+ register int vec1_x = x1 - x2;
1116
+ register int vec1_y = y1 - y2;
1117
+ register int vec2_x = x2 - x3;
1118
+ register int vec2_y = y2 - y3;
1119
+
1120
+ return (vec1_x * vec2_y) - (vec1_y * vec2_x);
1121
+ }
1122
+ */
1123
+
485
1124
  /*
486
1125
  * Ruby2D::Sound#ext_init
487
1126
  * Initialize sound structure data
@@ -510,7 +1149,22 @@ static R_VAL ruby2d_sound_ext_play(R_VAL self) {
510
1149
  #endif
511
1150
  R2D_Sound *snd;
512
1151
  r_data_get_struct(self, "@data", &sound_data_type, R2D_Sound, snd);
513
- R2D_PlaySound(snd);
1152
+ R2D_PlaySound(snd, r_test(r_iv_get(self, "@loop")));
1153
+ return R_NIL;
1154
+ }
1155
+
1156
+
1157
+ /*
1158
+ * Ruby2D::Sound#ext_stop
1159
+ */
1160
+ #if MRUBY
1161
+ static R_VAL ruby2d_sound_ext_stop(mrb_state* mrb, R_VAL self) {
1162
+ #else
1163
+ static R_VAL ruby2d_sound_ext_stop(R_VAL self) {
1164
+ #endif
1165
+ R2D_Sound *snd;
1166
+ r_data_get_struct(self, "@data", &sound_data_type, R2D_Sound, snd);
1167
+ R2D_StopSound(snd);
514
1168
  return R_NIL;
515
1169
  }
516
1170
 
@@ -798,6 +1452,30 @@ static void free_surface(SDL_Surface *surface) {
798
1452
  SDL_FreeSurface(surface);
799
1453
  }
800
1454
 
1455
+ /*
1456
+ * Free SDL texture structure used within the Ruby 2D `Pixmap` class
1457
+ */
1458
+ #if MRUBY
1459
+ static void free_sdl_texture(mrb_state *mrb, void *p_) {
1460
+ SDL_Texture *sdl_texure = (SDL_Texture *)p_;
1461
+ #else
1462
+ static void free_sdl_texture(SDL_Texture *sdl_texure) {
1463
+ #endif
1464
+ SDL_DestroyTexture(sdl_texure);
1465
+ }
1466
+
1467
+ /*
1468
+ * Free renderer structure used within the Ruby 2D `Canvas` class
1469
+ */
1470
+ #if MRUBY
1471
+ static void free_renderer(mrb_state *mrb, void *p_) {
1472
+ SDL_Renderer *renderer = (SDL_Renderer *)p_;
1473
+ #else
1474
+ static void free_renderer(SDL_Renderer *renderer) {
1475
+ #endif
1476
+ SDL_DestroyRenderer(renderer);
1477
+ }
1478
+
801
1479
 
802
1480
  /*
803
1481
  * Free music structure attached to Ruby 2D `Music` class
@@ -1236,11 +1914,11 @@ void Init_ruby2d() {
1236
1914
  // Ruby2D::Circle#self.ext_draw
1237
1915
  r_define_class_method(ruby2d_circle_class, "ext_draw", ruby2d_circle_ext_draw, r_args_req(1));
1238
1916
 
1239
- // Ruby2D::Image
1240
- R_CLASS ruby2d_image_class = r_define_class(ruby2d_module, "Image");
1917
+ // Ruby2D::Pixmap
1918
+ R_CLASS ruby2d_pixmap_class = r_define_class(ruby2d_module, "Pixmap");
1241
1919
 
1242
- // Ruby2D::Image#ext_load_image
1243
- r_define_class_method(ruby2d_image_class, "ext_load_image", ruby2d_image_ext_load_image, r_args_req(1));
1920
+ // Ruby2D::Pixmap#ext_load_pixmap
1921
+ r_define_method(ruby2d_pixmap_class, "ext_load_pixmap", ruby2d_pixmap_ext_load_pixmap, r_args_req(1));
1244
1922
 
1245
1923
  // Ruby2D::Text
1246
1924
  R_CLASS ruby2d_text_class = r_define_class(ruby2d_module, "Text");
@@ -1257,6 +1935,9 @@ void Init_ruby2d() {
1257
1935
  // Ruby2D::Sound#ext_play
1258
1936
  r_define_method(ruby2d_sound_class, "ext_play", ruby2d_sound_ext_play, r_args_none);
1259
1937
 
1938
+ // Ruby2D::Sound#ext_stop
1939
+ r_define_method(ruby2d_sound_class, "ext_stop", ruby2d_sound_ext_stop, r_args_none);
1940
+
1260
1941
  // Ruby2D::Sound#ext_get_volume
1261
1942
  r_define_method(ruby2d_sound_class, "ext_get_volume", ruby2d_sound_ext_get_volume, r_args_none);
1262
1943
 
@@ -1320,6 +2001,42 @@ void Init_ruby2d() {
1320
2001
  // Ruby2D::Texture#ext_delete
1321
2002
  r_define_method(ruby2d_texture_class, "ext_delete", ruby2d_texture_ext_delete, r_args_req(1));
1322
2003
 
2004
+ // Ruby2D::Canvas
2005
+ R_CLASS ruby2d_canvas_class = r_define_class(ruby2d_module, "Canvas");
2006
+
2007
+ // Ruby2D::Canvas#ext_create
2008
+ r_define_method(ruby2d_canvas_class, "ext_create", ruby2d_canvas_ext_create, r_args_req(1));
2009
+
2010
+ // Ruby2D::Canvas#ext_clear
2011
+ r_define_method(ruby2d_canvas_class, "ext_clear", ruby2d_canvas_ext_clear, r_args_req(1));
2012
+
2013
+ // Ruby2D::Canvas#ext_fill_rectangle
2014
+ r_define_method(ruby2d_canvas_class, "ext_fill_rectangle", ruby2d_canvas_ext_fill_rectangle, r_args_req(1));
2015
+
2016
+ // Ruby2D::Canvas#ext_draw_rectangle
2017
+ r_define_method(ruby2d_canvas_class, "ext_draw_rectangle", ruby2d_canvas_ext_draw_rectangle, r_args_req(1));
2018
+
2019
+ // Ruby2D::Canvas#ext_draw_line
2020
+ r_define_method(ruby2d_canvas_class, "ext_draw_line", ruby2d_canvas_ext_draw_line, r_args_req(1));
2021
+
2022
+ // Ruby2D::Canvas#ext_draw_polyline
2023
+ r_define_method(ruby2d_canvas_class, "ext_draw_polyline", ruby2d_canvas_ext_draw_polyline, r_args_req(2));
2024
+
2025
+ // Ruby2D::Canvas#ext_draw_polygon
2026
+ r_define_method(ruby2d_canvas_class, "ext_draw_polygon", ruby2d_canvas_ext_draw_polygon, r_args_req(2));
2027
+
2028
+ // Ruby2D::Canvas#ext_fill_polygon
2029
+ r_define_method(ruby2d_canvas_class, "ext_fill_polygon", ruby2d_canvas_ext_fill_polygon, r_args_req(2));
2030
+
2031
+ // Ruby2D::Canvas#ext_fill_ellipse
2032
+ r_define_method(ruby2d_canvas_class, "ext_fill_ellipse", ruby2d_canvas_ext_fill_ellipse, r_args_req(1));
2033
+
2034
+ // Ruby2D::Canvas#ext_draw_ellipse
2035
+ r_define_method(ruby2d_canvas_class, "ext_draw_ellipse", ruby2d_canvas_ext_draw_ellipse, r_args_req(1));
2036
+
2037
+ // Ruby2D::Canvas#ext_draw_pixmap
2038
+ r_define_method(ruby2d_canvas_class, "ext_draw_pixmap", ruby2d_canvas_ext_draw_pixmap, r_args_req(6));
2039
+
1323
2040
  // Ruby2D::Window
1324
2041
  R_CLASS ruby2d_window_class = r_define_class(ruby2d_module, "Window");
1325
2042