ruby2d 0.12.0 → 1.0.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 (619) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.md +7 -0
  3. data/README.md +141 -0
  4. data/USAGE.md +2435 -0
  5. data/assets/Rakefile +637 -0
  6. data/assets/build_support/CMakeLists.txt +94 -0
  7. data/assets/build_support/mruby/build_config.rb +34 -0
  8. data/assets/build_support/mruby/build_config_wasm.rb +30 -0
  9. data/assets/build_support/sdl_test.c +174 -0
  10. data/assets/deps.yaml +16 -0
  11. data/assets/platform/include/SDL3/SDL.h +91 -0
  12. data/assets/platform/include/SDL3/SDL_assert.h +705 -0
  13. data/assets/platform/include/SDL3/SDL_asyncio.h +550 -0
  14. data/assets/platform/include/SDL3/SDL_atomic.h +692 -0
  15. data/assets/platform/include/SDL3/SDL_audio.h +2370 -0
  16. data/assets/platform/include/SDL3/SDL_begin_code.h +553 -0
  17. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_bits.h +47 -27
  18. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_blendmode.h +59 -55
  19. data/assets/platform/include/SDL3/SDL_camera.h +535 -0
  20. data/assets/platform/include/SDL3/SDL_clipboard.h +331 -0
  21. data/assets/{include/SDL2/close_code.h → platform/include/SDL3/SDL_close_code.h} +9 -8
  22. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_copying.h +3 -1
  23. data/assets/platform/include/SDL3/SDL_cpuinfo.h +374 -0
  24. data/assets/platform/include/SDL3/SDL_dialog.h +343 -0
  25. data/assets/platform/include/SDL3/SDL_dlopennote.h +234 -0
  26. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_egl.h +11 -8
  27. data/assets/platform/include/SDL3/SDL_endian.h +645 -0
  28. data/assets/platform/include/SDL3/SDL_error.h +226 -0
  29. data/assets/platform/include/SDL3/SDL_events.h +1645 -0
  30. data/assets/platform/include/SDL3/SDL_filesystem.h +537 -0
  31. data/assets/platform/include/SDL3/SDL_gamepad.h +1656 -0
  32. data/assets/platform/include/SDL3/SDL_gpu.h +4608 -0
  33. data/assets/platform/include/SDL3/SDL_guid.h +106 -0
  34. data/assets/platform/include/SDL3/SDL_haptic.h +1461 -0
  35. data/assets/platform/include/SDL3/SDL_hidapi.h +571 -0
  36. data/assets/platform/include/SDL3/SDL_hints.h +5001 -0
  37. data/assets/platform/include/SDL3/SDL_init.h +507 -0
  38. data/assets/platform/include/SDL3/SDL_intrin.h +410 -0
  39. data/assets/platform/include/SDL3/SDL_iostream.h +1379 -0
  40. data/assets/platform/include/SDL3/SDL_joystick.h +1385 -0
  41. data/assets/platform/include/SDL3/SDL_keyboard.h +608 -0
  42. data/assets/platform/include/SDL3/SDL_keycode.h +347 -0
  43. data/assets/platform/include/SDL3/SDL_loadso.h +145 -0
  44. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_locale.h +40 -24
  45. data/assets/platform/include/SDL3/SDL_log.h +541 -0
  46. data/assets/platform/include/SDL3/SDL_main.h +704 -0
  47. data/assets/platform/include/SDL3/SDL_main_impl.h +151 -0
  48. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_messagebox.h +85 -48
  49. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_metal.h +29 -29
  50. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_misc.h +13 -12
  51. data/assets/platform/include/SDL3/SDL_mouse.h +813 -0
  52. data/assets/platform/include/SDL3/SDL_mutex.h +1117 -0
  53. data/assets/platform/include/SDL3/SDL_oldnames.h +1339 -0
  54. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengl.h +1247 -278
  55. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengl_glext.h +5 -1
  56. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles.h +6 -7
  57. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2.h +10 -11
  58. data/assets/platform/include/SDL3/SDL_pen.h +198 -0
  59. data/assets/platform/include/SDL3/SDL_pixels.h +1441 -0
  60. data/assets/{include/SDL2/SDL_test_log.h → platform/include/SDL3/SDL_platform.h} +25 -26
  61. data/assets/platform/include/SDL3/SDL_platform_defines.h +497 -0
  62. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_power.h +40 -20
  63. data/assets/platform/include/SDL3/SDL_process.h +441 -0
  64. data/assets/platform/include/SDL3/SDL_properties.h +572 -0
  65. data/assets/platform/include/SDL3/SDL_rect.h +528 -0
  66. data/assets/platform/include/SDL3/SDL_render.h +3028 -0
  67. data/assets/platform/include/SDL3/SDL_revision.h +59 -0
  68. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_scancode.h +59 -68
  69. data/assets/platform/include/SDL3/SDL_sensor.h +321 -0
  70. data/assets/platform/include/SDL3/SDL_stdinc.h +6186 -0
  71. data/assets/platform/include/SDL3/SDL_storage.h +686 -0
  72. data/assets/platform/include/SDL3/SDL_surface.h +1769 -0
  73. data/assets/platform/include/SDL3/SDL_system.h +840 -0
  74. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test.h +16 -22
  75. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_assert.h +27 -34
  76. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_common.h +109 -52
  77. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_compare.h +22 -14
  78. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_crc32.h +27 -30
  79. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_font.h +50 -49
  80. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_fuzzer.h +64 -79
  81. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_harness.h +47 -30
  82. data/assets/platform/include/SDL3/SDL_test_log.h +83 -0
  83. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_md5.h +21 -28
  84. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_memory.h +19 -16
  85. data/assets/platform/include/SDL3/SDL_thread.h +602 -0
  86. data/assets/platform/include/SDL3/SDL_time.h +249 -0
  87. data/assets/platform/include/SDL3/SDL_timer.h +454 -0
  88. data/assets/platform/include/SDL3/SDL_touch.h +184 -0
  89. data/assets/platform/include/SDL3/SDL_tray.h +544 -0
  90. data/assets/platform/include/SDL3/SDL_version.h +198 -0
  91. data/assets/platform/include/SDL3/SDL_video.h +3497 -0
  92. data/assets/platform/include/SDL3/SDL_vulkan.h +287 -0
  93. data/assets/platform/include/SDL3_image/SDL_image.h +3328 -0
  94. data/assets/platform/include/SDL3_mixer/SDL_mixer.h +3369 -0
  95. data/assets/platform/include/SDL3_ttf/SDL_textengine.h +181 -0
  96. data/assets/platform/include/SDL3_ttf/SDL_ttf.h +2833 -0
  97. data/assets/{include → platform/include}/mrbconf.h +42 -31
  98. data/assets/{include → platform/include}/mruby/array.h +3 -4
  99. data/assets/{include → platform/include}/mruby/boxing_nan.h +10 -0
  100. data/assets/platform/include/mruby/boxing_no.h +59 -0
  101. data/assets/{include → platform/include}/mruby/boxing_word.h +72 -26
  102. data/assets/platform/include/mruby/class.h +157 -0
  103. data/assets/{include → platform/include}/mruby/common.h +30 -1
  104. data/assets/{include → platform/include}/mruby/compile.h +52 -74
  105. data/assets/{include → platform/include}/mruby/data.h +2 -2
  106. data/assets/{include → platform/include}/mruby/debug.h +12 -5
  107. data/assets/{include → platform/include}/mruby/dump.h +7 -9
  108. data/assets/{include → platform/include}/mruby/endian.h +1 -1
  109. data/assets/platform/include/mruby/error.h +173 -0
  110. data/assets/platform/include/mruby/gc.h +79 -0
  111. data/assets/{include → platform/include}/mruby/hash.h +1 -7
  112. data/assets/platform/include/mruby/internal.h +282 -0
  113. data/assets/platform/include/mruby/irep.h +143 -0
  114. data/assets/{include → platform/include}/mruby/istruct.h +1 -1
  115. data/assets/platform/include/mruby/khash.h +455 -0
  116. data/assets/platform/include/mruby/mempool.h +19 -0
  117. data/assets/{include → platform/include}/mruby/numeric.h +7 -10
  118. data/assets/platform/include/mruby/object.h +51 -0
  119. data/assets/{include → platform/include}/mruby/opcode.h +5 -5
  120. data/assets/{include → platform/include}/mruby/ops.h +19 -6
  121. data/assets/platform/include/mruby/presym/id.h +1447 -0
  122. data/assets/{include → platform/include}/mruby/presym/scanning.h +10 -7
  123. data/assets/platform/include/mruby/presym/table.h +2893 -0
  124. data/assets/platform/include/mruby/presym.h +65 -0
  125. data/assets/platform/include/mruby/proc.h +184 -0
  126. data/assets/{include → platform/include}/mruby/range.h +0 -2
  127. data/assets/{include → platform/include}/mruby/string.h +33 -53
  128. data/assets/platform/include/mruby/throw.h +81 -0
  129. data/assets/{include → platform/include}/mruby/value.h +64 -29
  130. data/assets/{include → platform/include}/mruby/variable.h +6 -23
  131. data/assets/{include → platform/include}/mruby/version.h +7 -7
  132. data/assets/{include → platform/include}/mruby.h +238 -116
  133. data/assets/platform/macos-arm64/bin/mrbc +0 -0
  134. data/assets/platform/macos-arm64/lib/libSDL3.a +0 -0
  135. data/assets/platform/macos-arm64/lib/libSDL3_image.a +0 -0
  136. data/assets/platform/macos-arm64/lib/libSDL3_mixer.a +0 -0
  137. data/assets/platform/macos-arm64/lib/libSDL3_ttf.a +0 -0
  138. data/assets/platform/macos-arm64/lib/libmruby.a +0 -0
  139. data/assets/platform/wasm/lib/libFLAC.a +0 -0
  140. data/assets/platform/wasm/lib/libSDL3.a +0 -0
  141. data/assets/platform/wasm/lib/libSDL3_image.a +0 -0
  142. data/assets/platform/wasm/lib/libSDL3_mixer.a +0 -0
  143. data/assets/platform/wasm/lib/libSDL3_ttf.a +0 -0
  144. data/assets/platform/wasm/lib/libfreetype.a +0 -0
  145. data/assets/platform/wasm/lib/libharfbuzz.a +0 -0
  146. data/assets/platform/wasm/lib/libmruby.a +0 -0
  147. data/assets/platform/wasm/lib/libogg.a +0 -0
  148. data/assets/platform/wasm/lib/libplutosvg.a +0 -0
  149. data/assets/platform/wasm/lib/libplutovg.a +0 -0
  150. data/assets/platform/wasm/lib/libpng.a +0 -0
  151. data/assets/platform/wasm/lib/libpng16.a +0 -0
  152. data/assets/platform/wasm/lib/libvorbis.a +0 -0
  153. data/assets/platform/wasm/lib/libvorbisfile.a +0 -0
  154. data/assets/platform/wasm/lib/libzlibstatic.a +0 -0
  155. data/assets/platform/windows-arm64-mingw-ucrt/bin/mrbc.exe +0 -0
  156. data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3.a +0 -0
  157. data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3_image.a +0 -0
  158. data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3_mixer.a +0 -0
  159. data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3_ttf.a +0 -0
  160. data/assets/platform/windows-arm64-mingw-ucrt/lib/libmruby.a +0 -0
  161. data/assets/platform/windows-x86_64-mingw-ucrt/bin/mrbc.exe +0 -0
  162. data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3.a +0 -0
  163. data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3_image.a +0 -0
  164. data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3_mixer.a +0 -0
  165. data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3_ttf.a +0 -0
  166. data/assets/platform/windows-x86_64-mingw-ucrt/lib/libmruby.a +0 -0
  167. data/assets/resources/fonts/outfit/OFL.txt +93 -0
  168. data/assets/resources/fonts/outfit/outfit.ttf +0 -0
  169. data/assets/resources/fonts/roboto_mono/OFL.txt +91 -0
  170. data/assets/resources/fonts/roboto_mono/roboto_mono.ttf +0 -0
  171. data/assets/resources/icons/icon.icns +0 -0
  172. data/assets/resources/icons/icon.png +0 -0
  173. data/assets/resources/spritesheets/License.txt +28 -0
  174. data/assets/resources/spritesheets/spritesheet-backgrounds.png +0 -0
  175. data/assets/resources/spritesheets/spritesheet-backgrounds.xml +16 -0
  176. data/assets/resources/spritesheets/spritesheet-characters.png +0 -0
  177. data/assets/resources/spritesheets/spritesheet-characters.xml +47 -0
  178. data/assets/resources/spritesheets/spritesheet-enemies.png +0 -0
  179. data/assets/resources/spritesheets/spritesheet-enemies.xml +62 -0
  180. data/assets/resources/spritesheets/spritesheet-tiles.png +0 -0
  181. data/assets/resources/spritesheets/spritesheet-tiles.xml +316 -0
  182. data/assets/{wasm → resources/web}/template.html +1 -1
  183. data/assets/target.rb +131 -0
  184. data/bin/ruby2d +281 -82
  185. data/examples/astar.rb +269 -0
  186. data/examples/asteroids.rb +403 -0
  187. data/examples/bezier_editor.rb +96 -0
  188. data/examples/boids.rb +191 -0
  189. data/examples/bouncing_balls.rb +119 -0
  190. data/examples/breakout.rb +186 -0
  191. data/examples/constellations.rb +100 -0
  192. data/examples/dashboard.rb +133 -0
  193. data/examples/double_pendulum.rb +254 -0
  194. data/examples/falling_sand.rb +291 -0
  195. data/examples/fireworks.rb +110 -0
  196. data/examples/fluid_dynamics.rb +340 -0
  197. data/examples/fourier_epicycles.rb +142 -0
  198. data/examples/fractal_tree.rb +326 -0
  199. data/examples/game_of_life.rb +148 -0
  200. data/examples/gamepads.rb +333 -0
  201. data/examples/hill_driver.rb +613 -0
  202. data/examples/logo_animation.rb +251 -0
  203. data/examples/lorenz_attractor.rb +115 -0
  204. data/examples/mandelbrot.rb +207 -0
  205. data/examples/marching_squares.rb +200 -0
  206. data/examples/maze.rb +323 -0
  207. data/examples/nbody.rb +338 -0
  208. data/examples/outrun.rb +391 -0
  209. data/examples/pixel_paint.rb +313 -0
  210. data/examples/platformer.rb +335 -0
  211. data/examples/ray_casting_maze.rb +175 -0
  212. data/examples/shadow_casting.rb +151 -0
  213. data/examples/shape_recognizer.rb +908 -0
  214. data/examples/snake.rb +144 -0
  215. data/examples/sprite_sheets.rb +246 -0
  216. data/examples/swarm.rb +206 -0
  217. data/examples/tsp_annealing.rb +104 -0
  218. data/examples/ui_controls.rb +163 -0
  219. data/examples/wireframe_3d.rb +139 -0
  220. data/ext/ruby2d/audio.c +324 -0
  221. data/ext/ruby2d/canvas.c +1715 -494
  222. data/ext/ruby2d/ext.c +541 -0
  223. data/ext/ruby2d/extconf.rb +122 -145
  224. data/ext/ruby2d/font.c +566 -20
  225. data/ext/ruby2d/fps.c +92 -0
  226. data/ext/ruby2d/image.c +466 -41
  227. data/ext/ruby2d/ruby2d.c +374 -1890
  228. data/ext/ruby2d/ruby2d.h +840 -460
  229. data/ext/ruby2d/shapes.c +931 -101
  230. data/ext/ruby2d/text.c +586 -21
  231. data/ext/ruby2d/window.c +1693 -283
  232. data/lib/ruby2d/atlas_parser.rb +194 -0
  233. data/lib/ruby2d/audio.rb +73 -0
  234. data/lib/ruby2d/benchmark.rb +259 -0
  235. data/lib/ruby2d/bitmap_text.rb +155 -0
  236. data/lib/ruby2d/button.rb +402 -0
  237. data/lib/ruby2d/canvas.rb +703 -279
  238. data/lib/ruby2d/circle.rb +206 -29
  239. data/lib/ruby2d/cli/browser.rb +314 -0
  240. data/lib/ruby2d/cli/build.rb +471 -257
  241. data/lib/ruby2d/cli/colorize.rb +7 -5
  242. data/lib/ruby2d/cli/examples.rb +127 -0
  243. data/lib/ruby2d/cli/launch.rb +24 -39
  244. data/lib/ruby2d/cli/lib_files.rb +48 -0
  245. data/lib/ruby2d/cli/messages.rb +40 -0
  246. data/lib/ruby2d/cli/setup.rb +273 -0
  247. data/lib/ruby2d/cli/static_server.rb +160 -0
  248. data/lib/ruby2d/cli/usage.rb +255 -0
  249. data/lib/ruby2d/color.rb +191 -69
  250. data/lib/ruby2d/core.rb +37 -19
  251. data/lib/ruby2d/deps_help.rb +89 -0
  252. data/lib/ruby2d/dsl.rb +51 -12
  253. data/lib/ruby2d/ellipse.rb +228 -0
  254. data/lib/ruby2d/exceptions.rb +0 -2
  255. data/lib/ruby2d/font.rb +34 -74
  256. data/lib/ruby2d/gamepad.rb +323 -0
  257. data/lib/ruby2d/gem_paths.rb +19 -0
  258. data/lib/ruby2d/image.rb +155 -52
  259. data/lib/ruby2d/interactive.rb +103 -0
  260. data/lib/ruby2d/json_parser.rb +268 -0
  261. data/lib/ruby2d/line.rb +194 -85
  262. data/lib/ruby2d/mruby_compat.rb +12 -0
  263. data/lib/ruby2d/polygon.rb +297 -0
  264. data/lib/ruby2d/polyline.rb +368 -0
  265. data/lib/ruby2d/quad.rb +358 -94
  266. data/lib/ruby2d/rectangle.rb +77 -19
  267. data/lib/ruby2d/renderable.rb +411 -11
  268. data/lib/ruby2d/sprite.rb +471 -180
  269. data/lib/ruby2d/sprite_sheet.rb +64 -0
  270. data/lib/ruby2d/square.rb +29 -17
  271. data/lib/ruby2d/text.rb +196 -65
  272. data/lib/ruby2d/tileset.rb +139 -81
  273. data/lib/ruby2d/triangle.rb +324 -89
  274. data/lib/ruby2d/version.rb +1 -3
  275. data/lib/ruby2d/vertices.rb +62 -85
  276. data/lib/ruby2d/warnings.rb +29 -0
  277. data/lib/ruby2d/window/class_methods.rb +218 -0
  278. data/lib/ruby2d/window/gamepad_events.rb +141 -0
  279. data/lib/ruby2d/window/key_events.rb +74 -0
  280. data/lib/ruby2d/window/mouse_events.rb +171 -0
  281. data/lib/ruby2d/window/object_events.rb +168 -0
  282. data/lib/ruby2d/window.rb +632 -585
  283. data/lib/ruby2d.rb +14 -19
  284. metadata +275 -428
  285. data/assets/app.icns +0 -0
  286. data/assets/include/GLES2/gl2.h +0 -656
  287. data/assets/include/GLES2/gl2ext.h +0 -3949
  288. data/assets/include/GLES2/gl2ext_angle.h +0 -701
  289. data/assets/include/GLES2/gl2platform.h +0 -27
  290. data/assets/include/GLES3/gl3.h +0 -1192
  291. data/assets/include/GLES3/gl31.h +0 -1507
  292. data/assets/include/GLES3/gl32.h +0 -1808
  293. data/assets/include/GLES3/gl3platform.h +0 -27
  294. data/assets/include/KHR/khrplatform.h +0 -290
  295. data/assets/include/SDL2/SDL.h +0 -233
  296. data/assets/include/SDL2/SDL_assert.h +0 -326
  297. data/assets/include/SDL2/SDL_atomic.h +0 -415
  298. data/assets/include/SDL2/SDL_audio.h +0 -1500
  299. data/assets/include/SDL2/SDL_clipboard.h +0 -141
  300. data/assets/include/SDL2/SDL_config.h +0 -61
  301. data/assets/include/SDL2/SDL_config_android.h +0 -194
  302. data/assets/include/SDL2/SDL_config_emscripten.h +0 -218
  303. data/assets/include/SDL2/SDL_config_iphoneos.h +0 -217
  304. data/assets/include/SDL2/SDL_config_macosx.h +0 -277
  305. data/assets/include/SDL2/SDL_config_minimal.h +0 -95
  306. data/assets/include/SDL2/SDL_config_ngage.h +0 -89
  307. data/assets/include/SDL2/SDL_config_os2.h +0 -207
  308. data/assets/include/SDL2/SDL_config_pandora.h +0 -141
  309. data/assets/include/SDL2/SDL_config_windows.h +0 -331
  310. data/assets/include/SDL2/SDL_config_wingdk.h +0 -253
  311. data/assets/include/SDL2/SDL_config_winrt.h +0 -220
  312. data/assets/include/SDL2/SDL_config_xbox.h +0 -235
  313. data/assets/include/SDL2/SDL_cpuinfo.h +0 -594
  314. data/assets/include/SDL2/SDL_endian.h +0 -348
  315. data/assets/include/SDL2/SDL_error.h +0 -163
  316. data/assets/include/SDL2/SDL_events.h +0 -1166
  317. data/assets/include/SDL2/SDL_filesystem.h +0 -149
  318. data/assets/include/SDL2/SDL_gamecontroller.h +0 -1074
  319. data/assets/include/SDL2/SDL_gesture.h +0 -117
  320. data/assets/include/SDL2/SDL_guid.h +0 -100
  321. data/assets/include/SDL2/SDL_haptic.h +0 -1341
  322. data/assets/include/SDL2/SDL_hidapi.h +0 -451
  323. data/assets/include/SDL2/SDL_hints.h +0 -2569
  324. data/assets/include/SDL2/SDL_image.h +0 -2173
  325. data/assets/include/SDL2/SDL_joystick.h +0 -1066
  326. data/assets/include/SDL2/SDL_keyboard.h +0 -353
  327. data/assets/include/SDL2/SDL_keycode.h +0 -358
  328. data/assets/include/SDL2/SDL_loadso.h +0 -115
  329. data/assets/include/SDL2/SDL_log.h +0 -404
  330. data/assets/include/SDL2/SDL_main.h +0 -275
  331. data/assets/include/SDL2/SDL_mixer.h +0 -2784
  332. data/assets/include/SDL2/SDL_mouse.h +0 -465
  333. data/assets/include/SDL2/SDL_mutex.h +0 -471
  334. data/assets/include/SDL2/SDL_name.h +0 -33
  335. data/assets/include/SDL2/SDL_pixels.h +0 -644
  336. data/assets/include/SDL2/SDL_platform.h +0 -261
  337. data/assets/include/SDL2/SDL_quit.h +0 -58
  338. data/assets/include/SDL2/SDL_rect.h +0 -376
  339. data/assets/include/SDL2/SDL_render.h +0 -1919
  340. data/assets/include/SDL2/SDL_revision.h +0 -6
  341. data/assets/include/SDL2/SDL_rwops.h +0 -841
  342. data/assets/include/SDL2/SDL_sensor.h +0 -322
  343. data/assets/include/SDL2/SDL_shape.h +0 -155
  344. data/assets/include/SDL2/SDL_stdinc.h +0 -830
  345. data/assets/include/SDL2/SDL_surface.h +0 -997
  346. data/assets/include/SDL2/SDL_system.h +0 -623
  347. data/assets/include/SDL2/SDL_syswm.h +0 -386
  348. data/assets/include/SDL2/SDL_test_images.h +0 -78
  349. data/assets/include/SDL2/SDL_test_random.h +0 -115
  350. data/assets/include/SDL2/SDL_thread.h +0 -464
  351. data/assets/include/SDL2/SDL_timer.h +0 -222
  352. data/assets/include/SDL2/SDL_touch.h +0 -150
  353. data/assets/include/SDL2/SDL_ttf.h +0 -2316
  354. data/assets/include/SDL2/SDL_types.h +0 -29
  355. data/assets/include/SDL2/SDL_version.h +0 -204
  356. data/assets/include/SDL2/SDL_video.h +0 -2150
  357. data/assets/include/SDL2/SDL_vulkan.h +0 -215
  358. data/assets/include/SDL2/begin_code.h +0 -187
  359. data/assets/include/mruby/boxing_no.h +0 -58
  360. data/assets/include/mruby/class.h +0 -108
  361. data/assets/include/mruby/error.h +0 -147
  362. data/assets/include/mruby/gc.h +0 -94
  363. data/assets/include/mruby/irep.h +0 -147
  364. data/assets/include/mruby/khash.h +0 -284
  365. data/assets/include/mruby/object.h +0 -43
  366. data/assets/include/mruby/presym/disable.h +0 -70
  367. data/assets/include/mruby/presym/enable.h +0 -37
  368. data/assets/include/mruby/presym.h +0 -40
  369. data/assets/include/mruby/proc.h +0 -211
  370. data/assets/include/mruby/throw.h +0 -66
  371. data/assets/macos/universal/bin/mrbc +0 -0
  372. data/assets/macos/universal/lib/libFLAC.a +0 -0
  373. data/assets/macos/universal/lib/libSDL2.a +0 -0
  374. data/assets/macos/universal/lib/libSDL2_image.a +0 -0
  375. data/assets/macos/universal/lib/libSDL2_mixer.a +0 -0
  376. data/assets/macos/universal/lib/libSDL2_ttf.a +0 -0
  377. data/assets/macos/universal/lib/libavif.a +0 -0
  378. data/assets/macos/universal/lib/libbrotlicommon-static.a +0 -0
  379. data/assets/macos/universal/lib/libbrotlidec-static.a +0 -0
  380. data/assets/macos/universal/lib/libfreetype.a +0 -0
  381. data/assets/macos/universal/lib/libgraphite2.a +0 -0
  382. data/assets/macos/universal/lib/libharfbuzz.a +0 -0
  383. data/assets/macos/universal/lib/libhwy.a +0 -0
  384. data/assets/macos/universal/lib/libjpeg.a +0 -0
  385. data/assets/macos/universal/lib/libjxl.a +0 -0
  386. data/assets/macos/universal/lib/libmodplug.a +0 -0
  387. data/assets/macos/universal/lib/libmpg123.a +0 -0
  388. data/assets/macos/universal/lib/libmruby.a +0 -0
  389. data/assets/macos/universal/lib/libogg.a +0 -0
  390. data/assets/macos/universal/lib/libpng.a +0 -0
  391. data/assets/macos/universal/lib/libtiff.a +0 -0
  392. data/assets/macos/universal/lib/libvorbis.a +0 -0
  393. data/assets/macos/universal/lib/libvorbisfile.a +0 -0
  394. data/assets/macos/universal/lib/libwebp.a +0 -0
  395. data/assets/macos/universal/lib/libzstd.a +0 -0
  396. data/assets/test_media/README.md +0 -3
  397. data/assets/test_media/bitstream_vera/COPYRIGHT.txt +0 -124
  398. data/assets/test_media/bitstream_vera/vera.ttf +0 -0
  399. data/assets/test_media/boom.png +0 -0
  400. data/assets/test_media/coin.png +0 -0
  401. data/assets/test_media/colors.png +0 -0
  402. data/assets/test_media/controller.png +0 -0
  403. data/assets/test_media/dial.wav +0 -0
  404. data/assets/test_media/hero.png +0 -0
  405. data/assets/test_media/image.bmp +0 -0
  406. data/assets/test_media/image.jpg +0 -0
  407. data/assets/test_media/image.png +0 -0
  408. data/assets/test_media/music.flac +0 -0
  409. data/assets/test_media/music.mp3 +0 -0
  410. data/assets/test_media/music.ogg +0 -0
  411. data/assets/test_media/music.wav +0 -0
  412. data/assets/test_media/originals/boom.pxm +0 -0
  413. data/assets/test_media/originals/coin.pxm +0 -0
  414. data/assets/test_media/originals/controller.sketch +0 -0
  415. data/assets/test_media/originals/hero.pxm +0 -0
  416. data/assets/test_media/originals/image.pxm +0 -0
  417. data/assets/test_media/originals/music.caf +0 -0
  418. data/assets/test_media/originals/texture_atlas.pxm +0 -0
  419. data/assets/test_media/rondo_alla_turka.ogg +0 -0
  420. data/assets/test_media/sound.flac +0 -0
  421. data/assets/test_media/sound.mp3 +0 -0
  422. data/assets/test_media/sound.ogg +0 -0
  423. data/assets/test_media/sound.wav +0 -0
  424. data/assets/test_media/sprite_sheet.png +0 -0
  425. data/assets/test_media/texture_atlas.png +0 -0
  426. data/assets/wasm/libmruby.a +0 -0
  427. data/assets/windows/mingw-w64-ucrt-x86_64/bin/mrbc.exe +0 -0
  428. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libFLAC.a +0 -0
  429. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libLerc.a +0 -0
  430. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2.a +0 -0
  431. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_image.a +0 -0
  432. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_mixer.a +0 -0
  433. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_ttf.a +0 -0
  434. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlicommon.a +0 -0
  435. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlidec.a +0 -0
  436. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbz2.a +0 -0
  437. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libdeflate.a +0 -0
  438. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libfreetype.a +0 -0
  439. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libglew32.a +0 -0
  440. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libgraphite2.a +0 -0
  441. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libharfbuzz.a +0 -0
  442. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libhwy.a +0 -0
  443. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjbig.a +0 -0
  444. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjpeg.a +0 -0
  445. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjxl.a +0 -0
  446. data/assets/windows/mingw-w64-ucrt-x86_64/lib/liblzma.a +0 -0
  447. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmodplug.a +0 -0
  448. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmpg123.a +0 -0
  449. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmruby.a +0 -0
  450. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libogg.a +0 -0
  451. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopus.a +0 -0
  452. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopusfile.a +0 -0
  453. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libpng.a +0 -0
  454. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libsndfile.a +0 -0
  455. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libssp.a +0 -1
  456. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libstdc++.a +0 -0
  457. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libtiff.a +0 -0
  458. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbis.a +0 -0
  459. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbisfile.a +0 -0
  460. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libwebp.a +0 -0
  461. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libz.a +0 -0
  462. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libzstd.a +0 -0
  463. data/assets/windows/mingw-w64-x86_64/bin/mrbc.exe +0 -0
  464. data/assets/windows/mingw-w64-x86_64/lib/libFLAC.a +0 -0
  465. data/assets/windows/mingw-w64-x86_64/lib/libLerc.a +0 -0
  466. data/assets/windows/mingw-w64-x86_64/lib/libSDL2.a +0 -0
  467. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_image.a +0 -0
  468. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_mixer.a +0 -0
  469. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_ttf.a +0 -0
  470. data/assets/windows/mingw-w64-x86_64/lib/libbrotlicommon.a +0 -0
  471. data/assets/windows/mingw-w64-x86_64/lib/libbrotlidec.a +0 -0
  472. data/assets/windows/mingw-w64-x86_64/lib/libbz2.a +0 -0
  473. data/assets/windows/mingw-w64-x86_64/lib/libdeflate.a +0 -0
  474. data/assets/windows/mingw-w64-x86_64/lib/libfreetype.a +0 -0
  475. data/assets/windows/mingw-w64-x86_64/lib/libglew32.a +0 -0
  476. data/assets/windows/mingw-w64-x86_64/lib/libgraphite2.a +0 -0
  477. data/assets/windows/mingw-w64-x86_64/lib/libharfbuzz.a +0 -0
  478. data/assets/windows/mingw-w64-x86_64/lib/libhwy.a +0 -0
  479. data/assets/windows/mingw-w64-x86_64/lib/libjbig.a +0 -0
  480. data/assets/windows/mingw-w64-x86_64/lib/libjpeg.a +0 -0
  481. data/assets/windows/mingw-w64-x86_64/lib/libjxl.a +0 -0
  482. data/assets/windows/mingw-w64-x86_64/lib/liblzma.a +0 -0
  483. data/assets/windows/mingw-w64-x86_64/lib/libmodplug.a +0 -0
  484. data/assets/windows/mingw-w64-x86_64/lib/libmpg123.a +0 -0
  485. data/assets/windows/mingw-w64-x86_64/lib/libmruby.a +0 -0
  486. data/assets/windows/mingw-w64-x86_64/lib/libogg.a +0 -0
  487. data/assets/windows/mingw-w64-x86_64/lib/libopus.a +0 -0
  488. data/assets/windows/mingw-w64-x86_64/lib/libopusfile.a +0 -0
  489. data/assets/windows/mingw-w64-x86_64/lib/libpng.a +0 -0
  490. data/assets/windows/mingw-w64-x86_64/lib/libsndfile.a +0 -0
  491. data/assets/windows/mingw-w64-x86_64/lib/libssp.a +0 -1
  492. data/assets/windows/mingw-w64-x86_64/lib/libstdc++.a +0 -0
  493. data/assets/windows/mingw-w64-x86_64/lib/libtiff.a +0 -0
  494. data/assets/windows/mingw-w64-x86_64/lib/libvorbis.a +0 -0
  495. data/assets/windows/mingw-w64-x86_64/lib/libvorbisfile.a +0 -0
  496. data/assets/windows/mingw-w64-x86_64/lib/libwebp.a +0 -0
  497. data/assets/windows/mingw-w64-x86_64/lib/libz.a +0 -0
  498. data/assets/windows/mingw-w64-x86_64/lib/libzstd.a +0 -0
  499. data/assets/xcode/ios/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -98
  500. data/assets/xcode/ios/Assets.xcassets/Contents.json +0 -6
  501. data/assets/xcode/ios/Base.lproj/LaunchScreen.storyboard +0 -27
  502. data/assets/xcode/ios/Info.plist +0 -43
  503. data/assets/xcode/ios/MRuby.framework/Headers/mrbconf.h +0 -143
  504. data/assets/xcode/ios/MRuby.framework/Headers/mruby/array.h +0 -280
  505. data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_nan.h +0 -102
  506. data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_no.h +0 -56
  507. data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_word.h +0 -144
  508. data/assets/xcode/ios/MRuby.framework/Headers/mruby/class.h +0 -97
  509. data/assets/xcode/ios/MRuby.framework/Headers/mruby/common.h +0 -77
  510. data/assets/xcode/ios/MRuby.framework/Headers/mruby/compile.h +0 -195
  511. data/assets/xcode/ios/MRuby.framework/Headers/mruby/data.h +0 -75
  512. data/assets/xcode/ios/MRuby.framework/Headers/mruby/debug.h +0 -67
  513. data/assets/xcode/ios/MRuby.framework/Headers/mruby/dump.h +0 -196
  514. data/assets/xcode/ios/MRuby.framework/Headers/mruby/error.h +0 -75
  515. data/assets/xcode/ios/MRuby.framework/Headers/mruby/gc.h +0 -91
  516. data/assets/xcode/ios/MRuby.framework/Headers/mruby/hash.h +0 -215
  517. data/assets/xcode/ios/MRuby.framework/Headers/mruby/irep.h +0 -75
  518. data/assets/xcode/ios/MRuby.framework/Headers/mruby/istruct.h +0 -47
  519. data/assets/xcode/ios/MRuby.framework/Headers/mruby/khash.h +0 -274
  520. data/assets/xcode/ios/MRuby.framework/Headers/mruby/numeric.h +0 -161
  521. data/assets/xcode/ios/MRuby.framework/Headers/mruby/object.h +0 -44
  522. data/assets/xcode/ios/MRuby.framework/Headers/mruby/opcode.h +0 -69
  523. data/assets/xcode/ios/MRuby.framework/Headers/mruby/ops.h +0 -117
  524. data/assets/xcode/ios/MRuby.framework/Headers/mruby/proc.h +0 -131
  525. data/assets/xcode/ios/MRuby.framework/Headers/mruby/range.h +0 -49
  526. data/assets/xcode/ios/MRuby.framework/Headers/mruby/re.h +0 -16
  527. data/assets/xcode/ios/MRuby.framework/Headers/mruby/string.h +0 -444
  528. data/assets/xcode/ios/MRuby.framework/Headers/mruby/throw.h +0 -55
  529. data/assets/xcode/ios/MRuby.framework/Headers/mruby/value.h +0 -309
  530. data/assets/xcode/ios/MRuby.framework/Headers/mruby/variable.h +0 -136
  531. data/assets/xcode/ios/MRuby.framework/Headers/mruby/version.h +0 -110
  532. data/assets/xcode/ios/MRuby.framework/Headers/mruby.h +0 -1282
  533. data/assets/xcode/ios/MRuby.framework/Info.plist +0 -20
  534. data/assets/xcode/ios/MRuby.framework/MRuby +0 -0
  535. data/assets/xcode/ios/MyApp.xcodeproj/project.pbxproj +0 -368
  536. data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  537. data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  538. data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/xcshareddata/MyApp.xcscmblueprint +0 -30
  539. data/assets/xcode/ios/main.c +0 -1
  540. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json +0 -16
  541. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json +0 -6
  542. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Contents.json +0 -17
  543. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json +0 -16
  544. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json +0 -6
  545. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json +0 -16
  546. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json +0 -6
  547. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json +0 -16
  548. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json +0 -6
  549. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Contents.json +0 -17
  550. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json +0 -16
  551. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json +0 -6
  552. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json +0 -16
  553. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json +0 -6
  554. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json +0 -32
  555. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json +0 -16
  556. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json +0 -16
  557. data/assets/xcode/tvos/Assets.xcassets/Contents.json +0 -6
  558. data/assets/xcode/tvos/Assets.xcassets/LaunchImage.launchimage/Contents.json +0 -22
  559. data/assets/xcode/tvos/Info.plist +0 -30
  560. data/assets/xcode/tvos/MRuby.framework/Headers/mrbconf.h +0 -143
  561. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/array.h +0 -280
  562. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_nan.h +0 -102
  563. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_no.h +0 -56
  564. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_word.h +0 -144
  565. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/class.h +0 -97
  566. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/common.h +0 -77
  567. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/compile.h +0 -195
  568. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/data.h +0 -75
  569. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/debug.h +0 -67
  570. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/dump.h +0 -196
  571. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/error.h +0 -75
  572. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/gc.h +0 -91
  573. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/hash.h +0 -215
  574. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/irep.h +0 -75
  575. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/istruct.h +0 -47
  576. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/khash.h +0 -274
  577. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/numeric.h +0 -161
  578. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/object.h +0 -44
  579. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/opcode.h +0 -69
  580. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/ops.h +0 -117
  581. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/proc.h +0 -131
  582. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/range.h +0 -49
  583. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/re.h +0 -16
  584. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/string.h +0 -444
  585. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/throw.h +0 -55
  586. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/value.h +0 -309
  587. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/variable.h +0 -136
  588. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/version.h +0 -110
  589. data/assets/xcode/tvos/MRuby.framework/Headers/mruby.h +0 -1282
  590. data/assets/xcode/tvos/MRuby.framework/Info.plist +0 -20
  591. data/assets/xcode/tvos/MRuby.framework/MRuby +0 -0
  592. data/assets/xcode/tvos/MyApp.xcodeproj/project.pbxproj +0 -350
  593. data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  594. data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  595. data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/xcshareddata/MyApp.xcscmblueprint +0 -30
  596. data/assets/xcode/tvos/main.c +0 -1
  597. data/ext/ruby2d/common.c +0 -185
  598. data/ext/ruby2d/controllers.c +0 -110
  599. data/ext/ruby2d/gl.c +0 -398
  600. data/ext/ruby2d/gl2.c +0 -86
  601. data/ext/ruby2d/gl3.c +0 -304
  602. data/ext/ruby2d/gles.c +0 -302
  603. data/ext/ruby2d/input.c +0 -48
  604. data/ext/ruby2d/music.c +0 -127
  605. data/ext/ruby2d/sound.c +0 -132
  606. data/lib/ruby2d/cli/console.rb +0 -65
  607. data/lib/ruby2d/cli/enable_console.rb +0 -7
  608. data/lib/ruby2d/cli/platform.rb +0 -17
  609. data/lib/ruby2d/music.rb +0 -77
  610. data/lib/ruby2d/pixel.rb +0 -18
  611. data/lib/ruby2d/pixmap.rb +0 -39
  612. data/lib/ruby2d/pixmap_atlas.rb +0 -56
  613. data/lib/ruby2d/sound.rb +0 -61
  614. data/lib/ruby2d/texture.rb +0 -38
  615. /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2.h +0 -0
  616. /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2ext.h +0 -0
  617. /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2platform.h +0 -0
  618. /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_khrplatform.h +0 -0
  619. /data/assets/{include → platform/include}/mruby/re.h +0 -0
data/lib/ruby2d/canvas.rb CHANGED
@@ -1,315 +1,739 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Ruby2D::Canvas
4
2
 
5
3
  module Ruby2D
6
- #
7
- # Canvas provides a surface into which you can draw using primitives and render the contents
8
- # as if it were an image/texture.
9
- #
10
- # @example A basic Canvas positioned at (0, 0)
11
- # Canvas.new width: 320, height: 240
12
- # @example A Canvas that doesn't update texture on every draw method
13
- # Canvas.new width: 320, height: 240, update: false
14
- #
15
4
  class Canvas
16
5
  include Renderable
17
6
 
18
- # Create a Canvas.
19
- #
20
- # @param [Numeric] width The +width+ of the canvas in pixels
21
- # @param [Numeric] height The +height+ of the canvas in pixels
22
- # @param [Numeric] x
23
- # @param [Numeric] y
24
- # @param [Numeric] z
25
- # @param [Numeric] rotate Angle, default is 0
26
- # @param [String] fill Colour to clear the canvas, respects transparency
27
- # @param [String] color or +colour+ Tint the texture when rendering
28
- # @param [Numeric] opacity Opacity of the texture when rendering
29
- # @param [true, false] update If +true+ updates the texture for every draw/fill call
30
- # @param [true, false] show If +true+ the canvas is added to +Window+ automatically.
7
+ # Canvas uses `tint` instead of `color` — the canvas has its own pixel
8
+ # buffer; tint modulates the texture when drawn (white = untinted) and
9
+ # also acts as the default color for `canvas.fill_*` / `stroke_*` /
10
+ # `draw_*` methods when none is passed.
11
+ undef_method :color, :color=, :colour, :colour=
12
+
13
+ attr_accessor :width, :height, :rotate
14
+ attr_reader :x, :y, :fill
15
+
16
+ # Create a canvas with the given dimensions
31
17
  def initialize(width:, height:, x: 0, y: 0, z: 0, rotate: 0,
32
- fill: [0, 0, 0, 0], color: nil, colour: nil, opacity: nil,
33
- update: true, show: true)
34
- @x = x
35
- @y = y
18
+ fill: [0, 0, 0, 0], tint: nil, opacity: nil,
19
+ add: true, visible: true)
20
+ self.x = x
21
+ self.y = y
36
22
  @z = z
37
23
  @width = width
38
24
  @height = height
39
25
  @rotate = rotate
26
+ @_user_rx = nil
27
+ @_user_ry = nil
40
28
  @fill = Color.new(fill)
41
- self.color = color || colour || 'white'
42
- color.opacity = opacity if opacity
43
- @update = update
44
-
45
- ext_create([@width, @height, @fill.r, @fill.g, @fill.b, @fill.a]) # sets @ext_pixel_data
46
- @texture = Texture.new(@ext_pixel_data, @width, @height)
47
- add if show
48
- end
49
-
50
- # Clear the entire canvas, replacing every pixel with fill colour without blending.
51
- # @param [Color] fill_color
52
- def clear(fill_color = @fill)
53
- color = fill_color || @fill
54
- ext_clear([color.r, color.g, color.b, color.a])
55
- update_texture if @update
56
- end
57
-
58
- # Draw a filled triangle with a single colour or per-vertex colour blending.
59
- # @param [Numeric] x1
60
- # @param [Numeric] y1
61
- # @param [Numeric] x2
62
- # @param [Numeric] y2
63
- # @param [Numeric] x3
64
- # @param [Numeric] y3
65
- # @param [Color, Color::Set] color (or +colour+) Set one or per-vertex colour
66
- def fill_triangle(x1:, y1:, x2:, y2:, x3:, y3:, color: nil, colour: nil)
67
- fill_polygon coordinates: [x1, y1, x2, y2, x3, y3], color: color || colour
68
- end
69
-
70
- # Draw a filled quad(rilateral) with a single colour or per-vertex colour blending.
71
- # @param [Numeric] x1
72
- # @param [Numeric] y1
73
- # @param [Numeric] x2
74
- # @param [Numeric] y2
75
- # @param [Numeric] x3
76
- # @param [Numeric] y3
77
- # @param [Numeric] x4
78
- # @param [Numeric] y4
79
- # @param [Color, Color::Set] color (or +colour+) Set one or per-vertex colour
80
- def fill_quad(x1:, y1:, x2:, y2:, x3:, y3:, x4:, y4:, color: nil, colour: nil)
81
- fill_polygon coordinates: [x1, y1, x2, y2, x3, y3, x4, y4], color: color || colour
82
- end
83
-
84
- # Draw a circle.
85
- # @param [Numeric] x Centre
86
- # @param [Numeric] y Centre
87
- # @param [Numeric] radius
88
- # @param [Numeric] sectors The number of segments to subdivide the circumference.
89
- # @param [Numeric] stroke_width The thickness of the circle in pixels
90
- # @param [Color] color (or +colour+) The fill colour
91
- def draw_circle(x:, y:, radius:, sectors: 30, stroke_width: 1, color: nil, colour: nil)
92
- clr = color || colour
93
- clr = Color.new(clr) unless clr.is_a? Color
94
- ext_draw_ellipse([
95
- x, y, radius, radius, sectors, stroke_width,
96
- clr.r, clr.g, clr.b, clr.a
97
- ])
98
- update_texture if @update
99
- end
100
-
101
- # Draw an ellipse
102
- # @param [Numeric] x Centre
103
- # @param [Numeric] y Centre
104
- # @param [Numeric] xradius
105
- # @param [Numeric] yradius
106
- # @param [Numeric] sectors The number of segments to subdivide the circumference.
107
- # @param [Numeric] stroke_width The thickness of the circle in pixels
108
- # @param [Color] color (or +colour+) The fill colour
109
- def draw_ellipse(x:, y:, xradius:, yradius:, sectors: 30, stroke_width: 1, color: nil, colour: nil)
110
- clr = color || colour
111
- clr = Color.new(clr) unless clr.is_a? Color
112
- ext_draw_ellipse([
113
- x, y, xradius, yradius, sectors, stroke_width,
114
- clr.r, clr.g, clr.b, clr.a
115
- ])
116
- update_texture if @update
117
- end
118
-
119
- # Draw a filled circle.
120
- # @param [Numeric] x Centre
121
- # @param [Numeric] y Centre
122
- # @param [Numeric] radius
123
- # @param [Numeric] sectors The number of segments to subdivide the circumference.
124
- # @param [Color] color (or +colour+) The fill colour
125
- def fill_circle(x:, y:, radius:, sectors: 30, color: nil, colour: nil)
126
- clr = color || colour
127
- clr = Color.new(clr) unless clr.is_a? Color
128
- ext_fill_ellipse([
129
- x, y, radius, radius, sectors,
130
- clr.r, clr.g, clr.b, clr.a
131
- ])
132
- update_texture if @update
133
- end
134
-
135
- # Draw a filled ellipse.
136
- # @param [Numeric] x Centre
137
- # @param [Numeric] y Centre
138
- # @param [Numeric] xradius
139
- # @param [Numeric] yradius
140
- # @param [Numeric] sectors The number of segments to subdivide the circumference.
141
- # @param [Color] color (or +colour+) The fill colour
142
- def fill_ellipse(x:, y:, xradius:, yradius:, sectors: 30, color: nil, colour: nil)
143
- clr = color || colour
144
- clr = Color.new(clr) unless clr.is_a? Color
145
- ext_fill_ellipse([
146
- x, y, xradius, yradius, sectors,
147
- clr.r, clr.g, clr.b, clr.a
148
- ])
149
- update_texture if @update
150
- end
151
-
152
- # Draw a filled rectangle.
153
- # @param [Numeric] x
154
- # @param [Numeric] y
155
- # @param [Numeric] width
156
- # @param [Numeric] height
157
- # @param [Color] color (or +colour+) The fill colour
158
- def fill_rectangle(x:, y:, width:, height:, color: nil, colour: nil)
159
- clr = color || colour
160
- clr = Color.new(clr) unless clr.is_a? Color
161
- ext_fill_rectangle([
162
- x, y, width, height,
163
- clr.r, clr.g, clr.b, clr.a
164
- ])
165
- update_texture if @update
166
- end
167
-
168
- # Draw an outline of a triangle.
169
- # @param [Numeric] x1
170
- # @param [Numeric] y1
171
- # @param [Numeric] x2
172
- # @param [Numeric] y2
173
- # @param [Numeric] x3
174
- # @param [Numeric] y3
175
- # @param [Numeric] stroke_width The thickness of the rectangle in pixels
176
- # @param [Color] color (or +colour+) The line colour
177
- def draw_triangle(x1:, y1:, x2:, y2:, x3:, y3:, stroke_width: 1, color: nil, colour: nil)
178
- draw_polyline closed: true,
179
- coordinates: [x1, y1, x2, y2, x3, y3],
180
- color: color, colour: colour, stroke_width: stroke_width
181
- end
182
-
183
- # Draw an outline of a quad.
184
- # @param [Numeric] x1
185
- # @param [Numeric] y1
186
- # @param [Numeric] x2
187
- # @param [Numeric] y2
188
- # @param [Numeric] x3
189
- # @param [Numeric] y3
190
- # @param [Numeric] x4
191
- # @param [Numeric] y4
192
- # @param [Numeric] stroke_width The thickness of the rectangle in pixels
193
- # @param [Color] color (or +colour+) The line colour
194
- def draw_quad(x1:, y1:, x2:, y2:, x3:, y3:, x4:, y4:, stroke_width: 1, color: nil, colour: nil)
195
- draw_polyline closed: true,
196
- coordinates: [x1, y1, x2, y2, x3, y3, x4, y4],
197
- color: color, colour: colour, stroke_width: stroke_width
198
- end
199
-
200
- # Draw an outline of a rectangle
201
- # @param [Numeric] x
202
- # @param [Numeric] y
203
- # @param [Numeric] width
204
- # @param [Numeric] height
205
- # @param [Numeric] stroke_width The thickness of the rectangle in pixels
206
- # @param [Color] color (or +colour+) The line colour
207
- def draw_rectangle(x:, y:, width:, height:, stroke_width: 1, color: nil, colour: nil)
208
- clr = color || colour
209
- clr = Color.new(clr) unless clr.is_a? Color
210
- ext_draw_rectangle([
211
- x, y, width, height, stroke_width,
212
- clr.r, clr.g, clr.b, clr.a
213
- ])
214
- update_texture if @update
215
- end
216
-
217
- # Draw a straight line between two points
218
- # @param [Numeric] x1
219
- # @param [Numeric] y1
220
- # @param [Numeric] x2
221
- # @param [Numeric] y2
222
- # @param [Numeric] stroke_width The line's thickness in pixels; defaults to 1.
223
- # @param [Color] color (or +colour+) The line colour
224
- def draw_line(x1:, y1:, x2:, y2:, stroke_width: 1, color: nil, colour: nil)
225
- clr = color || colour
226
- clr = Color.new(clr) unless clr.is_a? Color
227
- ext_draw_line([
228
- x1, y1, x2, y2, stroke_width,
229
- clr.r, clr.g, clr.b, clr.a
230
- ])
231
- update_texture if @update
232
- end
233
-
234
- # Draw a poly-line between N points.
235
- # @param [Array] coordinates An array of numbers x1, y1, x2, y2 ... with at least three coordinates (6 values)
236
- # @param [Numeric] stroke_width The line's thickness in pixels; defaults to 1.
237
- # @param [Color] color (or +colour+) The line colour
238
- # @param [Boolean] closed Use +true+ to draw this as a closed shape
239
- def draw_polyline(coordinates:, stroke_width: 1, color: nil, colour: nil, closed: false)
240
- return if coordinates.nil? || coordinates.count < 6
241
-
242
- clr = color || colour
243
- clr = Color.new(clr) unless clr.is_a? Color
244
- config = [stroke_width, clr.r, clr.g, clr.b, clr.a]
245
- if closed
246
- ext_draw_polygon(config, coordinates)
29
+ self.tint = tint || 'white'
30
+ self.opacity = opacity unless opacity.nil?
31
+
32
+ @fill_r = @fill.r
33
+ @fill_g = @fill.g
34
+ @fill_b = @fill.b
35
+ @fill_a = @fill.a
36
+
37
+ Ext.canvas_create(self)
38
+ @visible = visible
39
+ self.add if add
40
+ end
41
+
42
+ # The canvas's tint color. The canvas's own pixel buffer is multiplied by
43
+ # this — `tint: 'red'` makes the canvas redder, not solid red.
44
+ def tint
45
+ @tint
46
+ end
47
+
48
+ def tint=(c)
49
+ @tint = Color.new(c)
50
+ end
51
+
52
+ # Get the tint's opacity. Canvas overrides `Renderable#opacity` because its
53
+ # modulating color is `@tint`, not `@color`.
54
+ def opacity
55
+ @tint&.opacity
56
+ end
57
+
58
+ def opacity=(value)
59
+ @tint.opacity = value
60
+ end
61
+
62
+ # Set the x position. The canvas draws its pixel buffer at (x, y) and has no
63
+ # symbolic alignment, so x must be a number — see Aligning to the window in
64
+ # USAGE.md.
65
+ def x=(value)
66
+ @x = _require_numeric_position(:x, value)
67
+ end
68
+
69
+ # Set the y position (numeric only see `x=`).
70
+ def y=(value)
71
+ @y = _require_numeric_position(:y, value)
72
+ end
73
+
74
+ # Get the rotation center x coordinate
75
+ def rx
76
+ @_user_rx.nil? ? @x + @width / 2.0 : @_user_rx
77
+ end
78
+
79
+ # Get the rotation center y coordinate
80
+ def ry
81
+ @_user_ry.nil? ? @y + @height / 2.0 : @_user_ry
82
+ end
83
+
84
+ # Set the rotation center x coordinate
85
+ def rx=(val)
86
+ @_user_rx = val
87
+ end
88
+
89
+ # Set the rotation center y coordinate
90
+ def ry=(val)
91
+ @_user_ry = val
92
+ end
93
+
94
+ # Fill a triangle. Specify vertices via `points:` or via numbered kwargs.
95
+ def fill_triangle(x1: nil, y1: nil, x2: nil, y2: nil, x3: nil, y3: nil,
96
+ points: nil, color: nil, colour: nil, opacity: nil)
97
+ if points
98
+ validate_points(points, 3, :fill_triangle)
99
+ x1, y1 = points[0]
100
+ x2, y2 = points[1]
101
+ x3, y3 = points[2]
102
+ end
103
+ return unless validate_vertex6(:fill_triangle, x1, y1, x2, y2, x3, y3)
104
+ opacity = clamp_opacity(opacity) if opacity
105
+ c = resolve_color_or_set(color || colour)
106
+ # A single flat color reads its channels straight into the C call; only
107
+ # a `Color::Set` or per-vertex opacity array builds the tuple array.
108
+ if c.is_a?(Color::Set) || opacity.is_a?(Array)
109
+ colors = per_vertex_fill_tuples(c, opacity, 3, :fill_triangle)
110
+ Ext.canvas_fill_triangle_lerp(self,
111
+ [x1, y1, *colors[0], x2, y2, *colors[1], x3, y3, *colors[2]])
247
112
  else
248
- ext_draw_polyline(config, coordinates)
113
+ Ext.canvas_fill_triangle(self, x1, y1, x2, y2, x3, y3,
114
+ c.r, c.g, c.b, opacity || c.a)
249
115
  end
250
- update_texture if @update
251
116
  end
252
117
 
253
- # Fill a polygon made up of N points.
254
- # @note Currently only supports convex polygons or simple polygons with one concave corner.
255
- # @note Supports per-vertex coloring, but the triangulation may change and affect the coloring.
256
- # @param [Array] coordinates An array of numbers x1, y1, x2, y2 ... with at least three coordinates (6 values)
257
- # @param [Color, Color::Set] color (or +colour+) Set one or per-vertex colour; at least one colour must be specified.
258
- def fill_polygon(coordinates:, color: nil, colour: nil)
259
- return if coordinates.nil? || coordinates.count < 6 || (color.nil? && colour.nil?)
118
+ # Fill a quadrilateral. Specify vertices via `points:` or via numbered kwargs.
119
+ def fill_quad(x1: nil, y1: nil, x2: nil, y2: nil, x3: nil, y3: nil, x4: nil, y4: nil,
120
+ points: nil, color: nil, colour: nil, opacity: nil)
121
+ if points
122
+ validate_points(points, 4, :fill_quad)
123
+ x1, y1 = points[0]
124
+ x2, y2 = points[1]
125
+ x3, y3 = points[2]
126
+ x4, y4 = points[3]
127
+ end
128
+ return unless validate_vertex8(:fill_quad, x1, y1, x2, y2, x3, y3, x4, y4)
129
+ opacity = clamp_opacity(opacity) if opacity
130
+ c = resolve_color_or_set(color || colour)
131
+ if c.is_a?(Color::Set) || opacity.is_a?(Array)
132
+ colors = per_vertex_fill_tuples(c, opacity, 4, :fill_quad)
133
+ # Split into triangles (0,1,2) and (0,2,3), each carrying its vertices'
134
+ # colors so the per-vertex gradient interpolates across the quad.
135
+ Ext.canvas_fill_triangle_lerp(self,
136
+ [x1, y1, *colors[0], x2, y2, *colors[1], x3, y3, *colors[2]])
137
+ Ext.canvas_fill_triangle_lerp(self,
138
+ [x1, y1, *colors[0], x3, y3, *colors[2], x4, y4, *colors[3]])
139
+ else
140
+ a = opacity || c.a
141
+ Ext.canvas_fill_triangle(self, x1, y1, x2, y2, x3, y3, c.r, c.g, c.b, a)
142
+ Ext.canvas_fill_triangle(self, x1, y1, x3, y3, x4, y4, c.r, c.g, c.b, a)
143
+ end
144
+ end
260
145
 
261
- colors = colors_to_a(color || colour)
262
- ext_fill_polygon(coordinates, colors)
263
- update_texture if @update
146
+ # Fill a rectangle at position (x,y) with the given width and height
147
+ def fill_rectangle(x:, y:, width:, height:, color: nil, colour: nil, opacity: nil)
148
+ return unless validate4(:fill_rectangle, x, y, width, height)
149
+ opacity = clamp_opacity(opacity) if opacity
150
+ c = resolve_color_or_set(color || colour)
151
+ # Per-vertex (corner) coloring or opacity needs the quad path; a single
152
+ # flat color uses the dedicated rectangle rasterizer.
153
+ if c.is_a?(Color::Set) || opacity.is_a?(Array)
154
+ fill_quad(
155
+ x1: x, y1: y, x2: x + width, y2: y,
156
+ x3: x + width, y3: y + height, x4: x, y4: y + height,
157
+ color: c, opacity: opacity
158
+ )
159
+ else
160
+ # `c` is already a drawable Color (or the canvas tint) from
161
+ # resolve_color_or_set; read it directly instead of allocating a second
162
+ # Color via resolve_draw_color.
163
+ Ext.canvas_fill_rectangle(self, x, y, width, height, c.r, c.g, c.b, opacity || c.a)
164
+ end
264
165
  end
265
166
 
266
- # Draw the pixmap at the specified location and size
267
- #
268
- # @note This API will evolve to be able to draw a portion of the pixmap; coming soon.
269
- # @param [Pixmap] pixmap
270
- # @param [Numeric] x
271
- # @param [Numeric] y
272
- # @param [Numeric] width Optional, specify to scale the size
273
- # @param [Numeric] height Optional, specify to scale the size
274
- # @param [Hash] crop Optional, specify a hash with `x:, y:, width:, height:` to crop from within the pixmap to draw.
275
- def draw_pixmap(pixmap, x:, y:, width: nil, height: nil, crop: nil)
276
- src_rect = crop ? [crop[:x], crop[:y], crop[:width], crop[:height]] : nil
277
- ext_draw_pixmap pixmap, src_rect, x, y, width, height
167
+ # Fill many rectangles with a single shared color in one call.
168
+ # rectangles is an array of `[x, y, width, height]` tuples.
169
+ def fill_rectangles(rectangles:, color: nil, colour: nil, opacity: nil)
170
+ return if rectangles.empty?
171
+ if opacity.is_a?(Array)
172
+ raise ArgumentError, 'fill_rectangles uses a single shared color and does not support a per-vertex opacity array'
173
+ end
174
+ opacity = clamp_opacity(opacity) if opacity
175
+
176
+ # One fused validate-and-build pass (`while`, not blocks this runs per
177
+ # draw call on N tuples, and block calls dominate on wasm mruby). A
178
+ # malformed tuple or non-Numeric coordinate is a programming mistake —
179
+ # raise, as the vertex-based methods do. A rect carrying a non-finite
180
+ # (NaN/Inf) coordinate or size is instead dropped rather than forwarded
181
+ # to C; the finite-only payload keeps the draw a clean no-op for the bad
182
+ # rects while still drawing the good ones.
183
+ payload = [0]
184
+ count = 0
185
+ i = 0
186
+ size = rectangles.size
187
+ while i < size
188
+ r = rectangles[i]
189
+ unless r.is_a?(Array) && r.length == 4
190
+ raise ArgumentError, 'rectangles must be an array of [x, y, width, height] tuples'
191
+ end
192
+ x = r[0]
193
+ y = r[1]
194
+ w = r[2]
195
+ h = r[3]
196
+ unless x.is_a?(Numeric) && y.is_a?(Numeric) && w.is_a?(Numeric) && h.is_a?(Numeric)
197
+ raise ArgumentError, 'fill_rectangles: every coordinate must be a number'
198
+ end
199
+ if finite4?(x, y, w, h)
200
+ count += 1
201
+ payload.push(x, y, w, h)
202
+ end
203
+ i += 1
204
+ end
205
+ return if count.zero?
206
+
207
+ payload[0] = count
208
+ c = resolve_draw_color(color || colour)
209
+ payload.push(c.r, c.g, c.b, opacity || c.a)
210
+ Ext.canvas_fill_rectangles(self, payload)
211
+ end
212
+
213
+ # Fill a regular grid of equal-size rectangles, each with its own color,
214
+ # in one call. The cell at column c, row r covers
215
+ # `(x + c*cell_w, y + r*cell_h, cell_w, cell_h)` and is colored by
216
+ # `colors[(r*cols + c)*4 .. +3]`. `colors` is a flat array of
217
+ # `cols*rows*4` floats in 0..1: `r0, g0, b0, a0, r1, g1, b1, a1, ...`.
218
+ # Cells with alpha 0 are skipped. Designed for grid renderings
219
+ # (fluid sims, heatmaps, tile fields) where per-rect FFI overhead
220
+ # dominates over the actual pixel work.
221
+ def fill_pixel_grid(cols:, rows:, cell_w:, cell_h:, colors:, x: 0, y: 0)
222
+ return if cols < 1 || rows < 1
223
+ return unless validate4(:fill_pixel_grid, cell_w, cell_h, x, y)
224
+ expected = cols * rows * 4
225
+ unless colors.length == expected
226
+ raise ArgumentError,
227
+ "colors must have #{expected} elements (cols*rows*4), got #{colors.length}"
228
+ end
229
+ Ext.canvas_fill_pixel_grid(self, [cols, rows, cell_w, cell_h, x, y], colors)
230
+ end
231
+
232
+ # Fill a square at position (x,y) with the given size
233
+ def fill_square(x:, y:, size:, color: nil, colour: nil, opacity: nil)
234
+ fill_rectangle(x: x, y: y, width: size, height: size, color: color, colour: colour, opacity: opacity)
235
+ end
236
+
237
+ # Fill a circle centered at (x,y) with the given radius
238
+ def fill_circle(x:, y:, radius:, color: nil, colour: nil, opacity: nil)
239
+ fill_ellipse(x: x, y: y, xradius: radius, yradius: radius, color: color, colour: colour, opacity: opacity)
240
+ end
241
+
242
+ # Fill an ellipse centered at (x,y) with the given x and y radii
243
+ def fill_ellipse(x:, y:, xradius:, yradius:, color: nil, colour: nil, opacity: nil)
244
+ if opacity.is_a?(Array)
245
+ raise ArgumentError, 'fill_ellipse/fill_circle is rasterized, not vertex-based, so it does not support a per-vertex opacity array'
246
+ end
247
+ return unless validate4(:fill_ellipse, x, y, xradius, yradius)
248
+ opacity = clamp_opacity(opacity) if opacity
249
+ c = resolve_draw_color(color || colour)
250
+ Ext.canvas_fill_ellipse(self, x, y, xradius, yradius, c.r, c.g, c.b, opacity || c.a)
251
+ end
252
+
253
+ # Fill a polygon defined by an array of [x, y] pairs.
254
+ # Concave polygons fill correctly: triangulation happens in C via
255
+ # ear clipping (R2D_TriangulatePolygon), shared with Polygon.new.
256
+ def fill_polygon(points:, color: nil, colour: nil, opacity: nil)
257
+ validate_point_pairs(points)
258
+ n = points.length
259
+ return if n < 3
260
+ return unless validate_pair_coords(points, :fill_polygon)
261
+
262
+ opacity = clamp_opacity(opacity) if opacity
263
+ c = resolve_color_or_set(color || colour)
264
+ # `while` loops, not blocks — this is a per-draw-call path over N points
265
+ # and block calls dominate on wasm mruby.
266
+ if c.is_a?(Color::Set) || opacity.is_a?(Array)
267
+ colors = per_vertex_fill_tuples(c, opacity, n, :fill_polygon)
268
+ payload = [n]
269
+ i = 0
270
+ while i < n
271
+ p = points[i]
272
+ col = colors[i]
273
+ payload.push(p[0], p[1], col[0], col[1], col[2], col[3])
274
+ i += 1
275
+ end
276
+ Ext.canvas_fill_polygon_lerp(self, payload)
277
+ else
278
+ payload = [n]
279
+ i = 0
280
+ while i < n
281
+ p = points[i]
282
+ payload.push(p[0], p[1])
283
+ i += 1
284
+ end
285
+ payload.push(c.r, c.g, c.b, opacity || c.a)
286
+ Ext.canvas_fill_polygon(self, payload)
287
+ end
288
+ end
289
+
290
+ # Stroke a triangle outline. Specify vertices via `points:` or via numbered
291
+ # kwargs. `color:` accepts a single color or a `Color::Set` of 3 (one per
292
+ # vertex) interpolated around the perimeter.
293
+ def stroke_triangle(x1: nil, y1: nil, x2: nil, y2: nil, x3: nil, y3: nil,
294
+ points: nil, stroke_width: 1, color: nil, colour: nil, opacity: nil)
295
+ if points
296
+ validate_points(points, 3, :stroke_triangle)
297
+ x1, y1 = points[0]
298
+ x2, y2 = points[1]
299
+ x3, y3 = points[2]
300
+ end
301
+ return unless validate_vertex6(:stroke_triangle, x1, y1, x2, y2, x3, y3)
302
+ colors = expand_stroke_colors(color || colour, 3, opacity, label: :stroke_triangle)
303
+ Ext.canvas_stroke_polygon(self, [3, x1, y1, x2, y2, x3, y3, stroke_width, *colors])
304
+ end
305
+
306
+ # Stroke a quadrilateral outline. Specify vertices via `points:` or via
307
+ # numbered kwargs. `color:` accepts a single color or a `Color::Set` of 4
308
+ # (one per vertex) interpolated around the perimeter.
309
+ def stroke_quad(x1: nil, y1: nil, x2: nil, y2: nil, x3: nil, y3: nil, x4: nil, y4: nil,
310
+ points: nil, stroke_width: 1, color: nil, colour: nil, opacity: nil)
311
+ if points
312
+ validate_points(points, 4, :stroke_quad)
313
+ x1, y1 = points[0]
314
+ x2, y2 = points[1]
315
+ x3, y3 = points[2]
316
+ x4, y4 = points[3]
317
+ end
318
+ return unless validate_vertex8(:stroke_quad, x1, y1, x2, y2, x3, y3, x4, y4)
319
+ colors = expand_stroke_colors(color || colour, 4, opacity, label: :stroke_quad)
320
+ Ext.canvas_stroke_polygon(self, [4, x1, y1, x2, y2, x3, y3, x4, y4, stroke_width, *colors])
321
+ end
322
+
323
+ # Stroke a rectangle outline at position (x,y) with the given width and height
324
+ def stroke_rectangle(x:, y:, width:, height:, stroke_width: 1, color: nil, colour: nil, opacity: nil)
325
+ stroke_quad(
326
+ x1: x, y1: y, x2: x + width, y2: y,
327
+ x3: x + width, y3: y + height, x4: x, y4: y + height,
328
+ stroke_width: stroke_width, color: color, colour: colour, opacity: opacity
329
+ )
330
+ end
331
+
332
+ # Stroke a square outline at position (x,y) with the given size
333
+ def stroke_square(x:, y:, size:, stroke_width: 1, color: nil, colour: nil, opacity: nil)
334
+ stroke_rectangle(x: x, y: y, width: size, height: size, stroke_width: stroke_width, color: color, colour: colour, opacity: opacity)
335
+ end
336
+
337
+ # Stroke a circle outline centered at (x,y) with the given radius.
338
+ # Single color only — sectors have no natural vertex identity.
339
+ def stroke_circle(x:, y:, radius:, sectors: 30, stroke_width: 1, color: nil, colour: nil, opacity: nil)
340
+ stroke_ellipse(x: x, y: y, xradius: radius, yradius: radius, sectors: sectors,
341
+ stroke_width: stroke_width, color: color, colour: colour, opacity: opacity)
342
+ end
343
+
344
+ # Stroke an ellipse outline centered at (x,y) with the given x and y radii.
345
+ # Single color only — sectors have no natural vertex identity.
346
+ def stroke_ellipse(x:, y:, xradius:, yradius:, sectors: 30, stroke_width: 1, color: nil, colour: nil, opacity: nil)
347
+ c = resolve_draw_color(color || colour)
348
+ a = (clamp_opacity(opacity) if opacity) || c.a
349
+ verts = []
350
+ colors = []
351
+ sectors.times do |i|
352
+ angle = 2.0 * Math::PI * i / sectors
353
+ verts << x + xradius * Math.cos(angle)
354
+ verts << y + yradius * Math.sin(angle)
355
+ colors << c.r << c.g << c.b << a
356
+ end
357
+ Ext.canvas_stroke_polygon(self, [sectors, *verts, stroke_width, *colors])
358
+ end
359
+
360
+ # Draw a line. Specify endpoints via `points:` or via numbered kwargs.
361
+ # Pass `dash:` (and optionally `gap:`) to draw a dashed line. `color:`
362
+ # accepts a single color or a `Color::Set` of 2 (start, end) for a
363
+ # gradient along the length.
364
+ def draw_line(x1: nil, y1: nil, x2: nil, y2: nil,
365
+ points: nil, stroke_width: 1, dash: 0, gap: 5,
366
+ color: nil, colour: nil, opacity: nil)
367
+ if points
368
+ validate_points(points, 2, :draw_line)
369
+ x1, y1 = points[0]
370
+ x2, y2 = points[1]
371
+ end
372
+ return unless validate_vertex4(:draw_line, x1, y1, x2, y2)
373
+ opacity = clamp_opacity(opacity) if opacity
374
+ c = resolve_color_or_set(color || colour)
375
+ if c.is_a?(Color::Set)
376
+ raise ArgumentError, 'Color::Set for draw_line must have 2 colors (start, end)' unless c.length == 2
377
+ Ext.canvas_draw_line_lerp(self, [
378
+ x1, y1, x2, y2, stroke_width,
379
+ c[0].r, c[0].g, c[0].b, opacity || c[0].a,
380
+ c[0].r, c[0].g, c[0].b, opacity || c[0].a,
381
+ c[1].r, c[1].g, c[1].b, opacity || c[1].a,
382
+ c[1].r, c[1].g, c[1].b, opacity || c[1].a,
383
+ dash, gap
384
+ ])
385
+ else
386
+ # `c` is already a drawable Color (or the canvas tint); read it directly
387
+ # instead of allocating a second Color via resolve_draw_color.
388
+ Ext.canvas_draw_line(self, x1, y1, x2, y2, stroke_width, c.r, c.g, c.b, opacity || c.a, dash, gap)
389
+ end
390
+ end
391
+
392
+ # Draw many line segments with a single shared color and stroke width in one call.
393
+ # segments is an array of `[[x, y], [x, y]]` endpoint pairs.
394
+ def draw_lines(segments:, stroke_width: 1, color: nil, colour: nil, opacity: nil)
395
+ return if segments.empty?
396
+
397
+ n = segments.length
398
+ # Fused validate-and-build pass (`while`, not blocks) — per draw call
399
+ # over N segments; see fill_rectangles.
400
+ payload = [n]
401
+ i = 0
402
+ while i < n
403
+ s = segments[i]
404
+ unless s.is_a?(Array) && s.length == 2
405
+ raise ArgumentError, 'segments must be an array of [[x, y], [x, y]] endpoint pairs'
406
+ end
407
+ a = s[0]
408
+ b = s[1]
409
+ unless a.is_a?(Array) && a.length == 2 && b.is_a?(Array) && b.length == 2
410
+ raise ArgumentError, 'segments must be an array of [[x, y], [x, y]] endpoint pairs'
411
+ end
412
+ payload.push(a[0], a[1], b[0], b[1])
413
+ i += 1
414
+ end
415
+ opacity = clamp_opacity(opacity) if opacity
416
+ c = resolve_draw_color(color || colour)
417
+ payload.push(stroke_width, c.r, c.g, c.b, opacity || c.a)
418
+ Ext.canvas_draw_lines(self, payload)
419
+ end
420
+
421
+ # Draw a polyline from an array of [x, y] pairs.
422
+ # Set `closed: true` to connect the last point back to the first.
423
+ # `color:` accepts a single color or a `Color::Set` of N (one per vertex)
424
+ # interpolated along the path.
425
+ def draw_polyline(points:, stroke_width: 1, color: nil, colour: nil, closed: false, opacity: nil)
426
+ validate_point_pairs(points)
427
+ n = points.length
428
+ return if n < 2
429
+ return unless validate_pair_coords(points, :draw_polyline)
430
+
431
+ colors = expand_stroke_colors(color || colour, n, opacity, label: :draw_polyline)
432
+ payload = [closed ? 1 : 0, n]
433
+ i = 0
434
+ while i < n
435
+ p = points[i]
436
+ payload.push(p[0], p[1])
437
+ i += 1
438
+ end
439
+ payload.push(stroke_width)
440
+ payload.concat(colors)
441
+ Ext.canvas_stroke_polyline(self, payload)
442
+ end
443
+
444
+ # Draw an Image onto this canvas at the given position and size
445
+ def draw_image(image, x: 0, y: 0, width: nil, height: nil)
446
+ w = width || image.width
447
+ h = height || image.height
448
+ return unless validate4(:draw_image, x, y, w, h)
449
+ Ext.canvas_draw_image(self, image, [x, y, w, h])
450
+ end
451
+
452
+ # Draw a Text onto this canvas at the given position and size, with optional color
453
+ def draw_text(text, x: 0, y: 0, width: nil, height: nil, color: nil, colour: nil, opacity: nil)
454
+ w = width || text.width
455
+ h = height || text.height
456
+ return unless validate4(:draw_text, x, y, w, h)
457
+ opacity = clamp_opacity(opacity) if opacity
458
+ c = resolve_draw_color(color || colour)
459
+ Ext.canvas_draw_text(self, text, [x, y, w, h, c.r, c.g, c.b, opacity || c.a])
278
460
  end
279
461
 
280
- def update
281
- update_texture
462
+ # Clear the canvas, resetting all pixels to the fill color (or the given
463
+ # color). The color may be passed positionally or via `color:`/`colour:`,
464
+ # matching the rest of the draw API. Optionally clear only a rectangular
465
+ # region.
466
+ def clear(fill_color = nil, color: nil, colour: nil, x: 0, y: 0, width: @width, height: @height)
467
+ return unless validate4(:clear, x, y, width, height)
468
+ input = fill_color || color || colour
469
+ c = input ? Color.new(input) : @fill
470
+ Ext.canvas_clear(self, [c.r, c.g, c.b, c.a, x, y, width, height])
471
+ end
472
+
473
+ # Render the canvas. Called with overrides for one-shot rendering inside a
474
+ # render block; with no arguments it draws the same frame the scene graph
475
+ # does (delegating to `_render_scene`). `width:`/`height:` scale the
476
+ # displayed output — the underlying pixel buffer is fixed at construction.
477
+ def render(x: nil, y: nil, width: nil, height: nil, rotate: nil,
478
+ tint: nil, opacity: nil)
479
+ if x.nil? && y.nil? && width.nil? && height.nil? && rotate.nil? &&
480
+ tint.nil? && opacity.nil?
481
+ return _render_scene
482
+ end
483
+
484
+ Window.render_ready_check
485
+
486
+ saved_x, saved_y = @x, @y
487
+ saved_width, saved_height = @width, @height
488
+ saved_rotate = @rotate
489
+ saved_tint = @tint
490
+
491
+ @x = x if x
492
+ @y = y if y
493
+ @width = width if width
494
+ @height = height if height
495
+ @rotate = rotate if rotate
496
+
497
+ if tint || opacity
498
+ @tint = tint ? Color.new(tint) : Color.new(saved_tint)
499
+ @tint.opacity = opacity if opacity
500
+ end
501
+
502
+ begin
503
+ Ext.canvas_draw(self, rx, ry)
504
+ ensure
505
+ @x, @y = saved_x, saved_y
506
+ @width, @height = saved_width, saved_height
507
+ @rotate = saved_rotate
508
+ @tint = saved_tint
509
+ end
282
510
  end
283
511
 
284
512
  private
285
513
 
286
- # Converts +color_or_set+ as a sequence of colour components; e.g. +[ r1, g1, b1, a1, ...]+
287
- # @param [Color, Color::Set] color_or_set
288
- # @return an array of r, g, b, a values
289
- def colors_to_a(color_or_set)
290
- if color_or_set.is_a? Color::Set
291
- color_a = []
292
- color_or_set.each do |clr|
293
- color_a << clr.r << clr.g << clr.b << clr.a
514
+ # Scene-graph draw hook (see Renderable#_render_scene): `render` with no
515
+ # overrides, minus its keyword handling — a zero-arg call into a
516
+ # keyword-heavy `render` still pays microseconds of keyword setup on wasm
517
+ # mruby.
518
+ def _render_scene
519
+ Ext.canvas_draw(self, rx, ry)
520
+ end
521
+ public :_render_scene
522
+
523
+ def validate_points(points, expected, name)
524
+ raise ArgumentError, "#{name} requires exactly #{expected} points" unless points.length == expected
525
+ validate_point_pairs(points)
526
+ end
527
+
528
+ # Validate a variable-length list of `[x, y]` pairs (e.g. fill_polygon,
529
+ # draw_polyline), which have no fixed point count. A `while` loop, not
530
+ # `all?` — these validators run per draw call on N-element inputs, and on
531
+ # wasm mruby every block invocation costs real time (see the batch draw
532
+ # methods, whose lib-side cost was dominated by validation block calls).
533
+ def validate_point_pairs(points)
534
+ raise ArgumentError, 'points must be an array of [x, y] pairs' unless points.is_a?(Array)
535
+
536
+ i = 0
537
+ size = points.size
538
+ while i < size
539
+ p = points[i]
540
+ raise ArgumentError, 'points must be an array of [x, y] pairs' unless p.is_a?(Array) && p.length == 2
541
+ i += 1
542
+ end
543
+ end
544
+
545
+ # Fused numeric + finiteness pass over `[x, y]` pairs: the pair-list
546
+ # equivalent of the fixed-arity `validate_vertex*` checks without the
547
+ # flattened copy or per-element blocks. Raises on a non-Numeric coordinate;
548
+ # returns false (skip the draw) when any coordinate is non-finite.
549
+ def validate_pair_coords(points, name)
550
+ finite = true
551
+ i = 0
552
+ size = points.size
553
+ while i < size
554
+ p = points[i]
555
+ x = p[0]
556
+ y = p[1]
557
+ unless x.is_a?(Numeric) && y.is_a?(Numeric)
558
+ raise ArgumentError,
559
+ "#{name}: every coordinate must be a number — pass all vertices via `points:` or the numbered kwargs"
294
560
  end
295
- return color_a
561
+ finite = false unless finite_value?(x) && finite_value?(y)
562
+ i += 1
296
563
  end
564
+ finite
565
+ end
566
+
567
+ # Validate a vertex-method coordinate list before it crosses into the C
568
+ # extension. Catches a missing numbered-kwarg vertex (left nil) or a
569
+ # non-numeric coordinate, which would otherwise surface as a cryptic
570
+ # "no implicit conversion to Float" from deep in the native call.
571
+ #
572
+ # Returns true when the draw should proceed. A genuine type error (a nil or
573
+ # non-Numeric coordinate) still raises, since that signals a programming
574
+ # mistake. A non-finite Numeric (NaN/Inf) instead returns false so the caller
575
+ # skips the draw — animation-safe, matching the no-mid-run-raise philosophy
576
+ # and the C rasterizer's isfinite no-op backstop.
577
+ #
578
+ # Fixed-arity variants, one per vertex-method width — a coords array
579
+ # argument (or a `*coords` splat) would allocate on every draw call, and
580
+ # each caller passes a fixed number of coordinates.
581
+ def validate_vertex4(name, x1, y1, x2, y2)
582
+ unless x1.is_a?(Numeric) && y1.is_a?(Numeric) &&
583
+ x2.is_a?(Numeric) && y2.is_a?(Numeric)
584
+ raise_vertex_type_error(name)
585
+ end
586
+ finite4?(x1, y1, x2, y2)
587
+ end
297
588
 
298
- color_or_set = Color.new(color_or_set) unless color_or_set.is_a? Color
299
- color_or_set.to_a
589
+ def validate_vertex6(name, x1, y1, x2, y2, x3, y3)
590
+ unless x1.is_a?(Numeric) && y1.is_a?(Numeric) &&
591
+ x2.is_a?(Numeric) && y2.is_a?(Numeric) &&
592
+ x3.is_a?(Numeric) && y3.is_a?(Numeric)
593
+ raise_vertex_type_error(name)
594
+ end
595
+ finite4?(x1, y1, x2, y2) && finite_value?(x3) && finite_value?(y3)
300
596
  end
301
597
 
302
- def update_texture
303
- @texture.delete
304
- @texture = Texture.new(@ext_pixel_data, @width, @height)
598
+ def validate_vertex8(name, x1, y1, x2, y2, x3, y3, x4, y4)
599
+ unless x1.is_a?(Numeric) && y1.is_a?(Numeric) &&
600
+ x2.is_a?(Numeric) && y2.is_a?(Numeric) &&
601
+ x3.is_a?(Numeric) && y3.is_a?(Numeric) &&
602
+ x4.is_a?(Numeric) && y4.is_a?(Numeric)
603
+ raise_vertex_type_error(name)
604
+ end
605
+ finite4?(x1, y1, x2, y2) && finite4?(x3, y3, x4, y4)
305
606
  end
306
607
 
307
- def render(x: @x, y: @y, width: @width, height: @height, color: @color, rotate: @rotate)
308
- vertices = Vertices.new(x, y, width, height, rotate)
608
+ def raise_vertex_type_error(name)
609
+ raise ArgumentError,
610
+ "#{name}: every coordinate must be a number — pass all vertices via `points:` or the numbered kwargs"
611
+ end
309
612
 
310
- @texture.draw(
311
- vertices.coordinates, vertices.texture_coordinates, color
312
- )
613
+ # True when the value is a finite Numeric — the single-value primitive the
614
+ # validators above compose. A non-finite (NaN/Inf) coordinate or size skips
615
+ # the draw rather than reaching the C rasterizer's integer casts (which the
616
+ # isfinite backstop also guards).
617
+ def finite_value?(v)
618
+ # Float and Integer cover every real caller; `respond_to?` is expensive
619
+ # on wasm mruby, so reserve that generic path for exotic Numerics.
620
+ case v
621
+ when Float then v.finite?
622
+ when Integer then true
623
+ when Numeric then v.respond_to?(:finite?) ? v.finite? : true
624
+ else false
625
+ end
626
+ end
627
+
628
+ # Fixed-arity finiteness check for the four-coordinate fill paths. A `*values`
629
+ # signature would allocate a splat array on every fill; every caller here
630
+ # passes exactly four values, so take them positionally instead.
631
+ def finite4?(a, b, c, d)
632
+ finite_value?(a) && finite_value?(b) && finite_value?(c) && finite_value?(d)
633
+ end
634
+
635
+ # Fixed-arity validate-and-finiteness for the four-value fill/draw paths,
636
+ # mirroring `validate_vertex4` (minus its `points:` hint — these methods
637
+ # take position/size values, not vertices): a non-Numeric value raises (a
638
+ # programming mistake), while a non-finite Numeric (NaN/Inf) returns false
639
+ # so the caller skips the draw (animation-safe).
640
+ def validate4(name, a, b, c, d)
641
+ unless a.is_a?(Numeric) && b.is_a?(Numeric) && c.is_a?(Numeric) && d.is_a?(Numeric)
642
+ raise ArgumentError, "#{name}: every coordinate must be a number"
643
+ end
644
+ finite4?(a, b, c, d)
645
+ end
646
+
647
+ # Clamp an `opacity:` argument (a scalar, a per-vertex array, or nil) into
648
+ # the valid 0.0..1.0 range. An out-of-range value would otherwise wrap the
649
+ # Uint8 alpha cast in the C extension into a wrong, near-opaque byte. Silent
650
+ # and animation-safe, matching `Color#opacity=`. nil passes through so the
651
+ # color's own alpha is used.
652
+ def clamp_opacity(opacity)
653
+ case opacity
654
+ when Numeric then opacity.clamp(0.0, 1.0)
655
+ when Array then opacity.map { |o| o.is_a?(Numeric) ? o.clamp(0.0, 1.0) : o }
656
+ else opacity
657
+ end
313
658
  end
659
+
660
+ # Resolve a draw color for immediate reading on the per-draw-call path.
661
+ # String colors and flat `[r, g, b(, a)]` numeric arrays go through
662
+ # `Color.for_render`'s shared cached instance and a passed-in Color is
663
+ # returned as-is — no defensive copy. Safe because every caller reads
664
+ # `.r/.g/.b/.a` into its payload immediately and never stores the result
665
+ # (the `@tint` fallback is already a shared instance). Other inputs keep
666
+ # the allocating `Color.new` path so invalid input raises exactly as
667
+ # before.
668
+ def resolve_draw_color(c)
669
+ return @tint unless c
670
+ return c if c.is_a?(Color)
671
+ return Color.for_render(c) if c.is_a?(String) || Color.rgba_array?(c)
672
+ Color.new(c)
673
+ end
674
+
675
+ # Same contract as `resolve_draw_color`, additionally passing through a
676
+ # `Color::Set` (or recognizing an array of colors as one via `Color.set`).
677
+ def resolve_color_or_set(c)
678
+ return c if c.is_a?(Color::Set)
679
+ return @tint unless c
680
+ return c if c.is_a?(Color)
681
+ return Color.for_render(c) if c.is_a?(String) || Color.rgba_array?(c)
682
+ Color.set(c)
683
+ end
684
+
685
+ # Build a fill's per-vertex `[r, g, b, a]` tuples for the lerp draw path.
686
+ # `c` is an already-resolved `Color` or `Color::Set` (see
687
+ # `resolve_color_or_set`) and `opacity` is already clamped — the caller
688
+ # resolves both first to decide the path, and only calls this when the
689
+ # color varies per vertex OR an opacity array is given, so a single color
690
+ # with a per-vertex `opacity:` array still fades across the fill (matching
691
+ # `Polyline`). The flat single-color case never gets here: callers read
692
+ # the resolved color's channels straight into the C call, allocating
693
+ # nothing.
694
+ def per_vertex_fill_tuples(c, opacity, count, name)
695
+ if c.is_a?(Color::Set) && c.length != count
696
+ raise ArgumentError, "Color::Set for #{name} must have #{count} colors. #{c.length} were given."
697
+ end
698
+ if opacity.is_a?(Array) && opacity.length != count
699
+ raise ArgumentError,
700
+ "opacity array for #{name} must have #{count} values, one per vertex. #{opacity.length} were given."
701
+ end
702
+
703
+ single = c.is_a?(Color::Set) ? nil : c
704
+ Array.new(count) do |i|
705
+ col = single || c[i]
706
+ a = opacity.is_a?(Array) ? opacity[i] : (opacity || col.a)
707
+ [col.r, col.g, col.b, a]
708
+ end
709
+ end
710
+
711
+ # Expand a single color or a Color::Set of vertex_count colors into a flat
712
+ # [r,g,b,a, r,g,b,a, ...] array of length vertex_count*4.
713
+ def expand_stroke_colors(input, vertex_count, opacity, label:)
714
+ opacity = clamp_opacity(opacity) if opacity
715
+ c = resolve_color_or_set(input)
716
+ if c.is_a?(Color::Set)
717
+ unless c.length == vertex_count
718
+ raise ArgumentError,
719
+ "Color::Set for #{label} must have #{vertex_count} colors. #{c.length} were given."
720
+ end
721
+ end
722
+ if opacity.is_a?(Array) && opacity.length != vertex_count
723
+ raise ArgumentError,
724
+ "opacity array for #{label} must have #{vertex_count} values. #{opacity.length} were given."
725
+ end
726
+
727
+ flat = Array.new(vertex_count * 4)
728
+ vertex_count.times do |i|
729
+ col = c.is_a?(Color::Set) ? c[i] : c
730
+ flat[i * 4] = col.r
731
+ flat[i * 4 + 1] = col.g
732
+ flat[i * 4 + 2] = col.b
733
+ flat[i * 4 + 3] = (opacity.is_a?(Array) ? opacity[i] : opacity) || col.a
734
+ end
735
+ flat
736
+ end
737
+
314
738
  end
315
739
  end