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.
- checksums.yaml +4 -4
- data/LICENSE.md +7 -0
- data/README.md +141 -0
- data/USAGE.md +2435 -0
- data/assets/Rakefile +637 -0
- data/assets/build_support/CMakeLists.txt +94 -0
- data/assets/build_support/mruby/build_config.rb +34 -0
- data/assets/build_support/mruby/build_config_wasm.rb +30 -0
- data/assets/build_support/sdl_test.c +174 -0
- data/assets/deps.yaml +16 -0
- data/assets/platform/include/SDL3/SDL.h +91 -0
- data/assets/platform/include/SDL3/SDL_assert.h +705 -0
- data/assets/platform/include/SDL3/SDL_asyncio.h +550 -0
- data/assets/platform/include/SDL3/SDL_atomic.h +692 -0
- data/assets/platform/include/SDL3/SDL_audio.h +2370 -0
- data/assets/platform/include/SDL3/SDL_begin_code.h +553 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_bits.h +47 -27
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_blendmode.h +59 -55
- data/assets/platform/include/SDL3/SDL_camera.h +535 -0
- data/assets/platform/include/SDL3/SDL_clipboard.h +331 -0
- data/assets/{include/SDL2/close_code.h → platform/include/SDL3/SDL_close_code.h} +9 -8
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_copying.h +3 -1
- data/assets/platform/include/SDL3/SDL_cpuinfo.h +374 -0
- data/assets/platform/include/SDL3/SDL_dialog.h +343 -0
- data/assets/platform/include/SDL3/SDL_dlopennote.h +234 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_egl.h +11 -8
- data/assets/platform/include/SDL3/SDL_endian.h +645 -0
- data/assets/platform/include/SDL3/SDL_error.h +226 -0
- data/assets/platform/include/SDL3/SDL_events.h +1645 -0
- data/assets/platform/include/SDL3/SDL_filesystem.h +537 -0
- data/assets/platform/include/SDL3/SDL_gamepad.h +1656 -0
- data/assets/platform/include/SDL3/SDL_gpu.h +4608 -0
- data/assets/platform/include/SDL3/SDL_guid.h +106 -0
- data/assets/platform/include/SDL3/SDL_haptic.h +1461 -0
- data/assets/platform/include/SDL3/SDL_hidapi.h +571 -0
- data/assets/platform/include/SDL3/SDL_hints.h +5001 -0
- data/assets/platform/include/SDL3/SDL_init.h +507 -0
- data/assets/platform/include/SDL3/SDL_intrin.h +410 -0
- data/assets/platform/include/SDL3/SDL_iostream.h +1379 -0
- data/assets/platform/include/SDL3/SDL_joystick.h +1385 -0
- data/assets/platform/include/SDL3/SDL_keyboard.h +608 -0
- data/assets/platform/include/SDL3/SDL_keycode.h +347 -0
- data/assets/platform/include/SDL3/SDL_loadso.h +145 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_locale.h +40 -24
- data/assets/platform/include/SDL3/SDL_log.h +541 -0
- data/assets/platform/include/SDL3/SDL_main.h +704 -0
- data/assets/platform/include/SDL3/SDL_main_impl.h +151 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_messagebox.h +85 -48
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_metal.h +29 -29
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_misc.h +13 -12
- data/assets/platform/include/SDL3/SDL_mouse.h +813 -0
- data/assets/platform/include/SDL3/SDL_mutex.h +1117 -0
- data/assets/platform/include/SDL3/SDL_oldnames.h +1339 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengl.h +1247 -278
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengl_glext.h +5 -1
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles.h +6 -7
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2.h +10 -11
- data/assets/platform/include/SDL3/SDL_pen.h +198 -0
- data/assets/platform/include/SDL3/SDL_pixels.h +1441 -0
- data/assets/{include/SDL2/SDL_test_log.h → platform/include/SDL3/SDL_platform.h} +25 -26
- data/assets/platform/include/SDL3/SDL_platform_defines.h +497 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_power.h +40 -20
- data/assets/platform/include/SDL3/SDL_process.h +441 -0
- data/assets/platform/include/SDL3/SDL_properties.h +572 -0
- data/assets/platform/include/SDL3/SDL_rect.h +528 -0
- data/assets/platform/include/SDL3/SDL_render.h +3028 -0
- data/assets/platform/include/SDL3/SDL_revision.h +59 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_scancode.h +59 -68
- data/assets/platform/include/SDL3/SDL_sensor.h +321 -0
- data/assets/platform/include/SDL3/SDL_stdinc.h +6186 -0
- data/assets/platform/include/SDL3/SDL_storage.h +686 -0
- data/assets/platform/include/SDL3/SDL_surface.h +1769 -0
- data/assets/platform/include/SDL3/SDL_system.h +840 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test.h +16 -22
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_assert.h +27 -34
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_common.h +109 -52
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_compare.h +22 -14
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_crc32.h +27 -30
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_font.h +50 -49
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_fuzzer.h +64 -79
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_harness.h +47 -30
- data/assets/platform/include/SDL3/SDL_test_log.h +83 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_md5.h +21 -28
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_memory.h +19 -16
- data/assets/platform/include/SDL3/SDL_thread.h +602 -0
- data/assets/platform/include/SDL3/SDL_time.h +249 -0
- data/assets/platform/include/SDL3/SDL_timer.h +454 -0
- data/assets/platform/include/SDL3/SDL_touch.h +184 -0
- data/assets/platform/include/SDL3/SDL_tray.h +544 -0
- data/assets/platform/include/SDL3/SDL_version.h +198 -0
- data/assets/platform/include/SDL3/SDL_video.h +3497 -0
- data/assets/platform/include/SDL3/SDL_vulkan.h +287 -0
- data/assets/platform/include/SDL3_image/SDL_image.h +3328 -0
- data/assets/platform/include/SDL3_mixer/SDL_mixer.h +3369 -0
- data/assets/platform/include/SDL3_ttf/SDL_textengine.h +181 -0
- data/assets/platform/include/SDL3_ttf/SDL_ttf.h +2833 -0
- data/assets/{include → platform/include}/mrbconf.h +42 -31
- data/assets/{include → platform/include}/mruby/array.h +3 -4
- data/assets/{include → platform/include}/mruby/boxing_nan.h +10 -0
- data/assets/platform/include/mruby/boxing_no.h +59 -0
- data/assets/{include → platform/include}/mruby/boxing_word.h +72 -26
- data/assets/platform/include/mruby/class.h +157 -0
- data/assets/{include → platform/include}/mruby/common.h +30 -1
- data/assets/{include → platform/include}/mruby/compile.h +52 -74
- data/assets/{include → platform/include}/mruby/data.h +2 -2
- data/assets/{include → platform/include}/mruby/debug.h +12 -5
- data/assets/{include → platform/include}/mruby/dump.h +7 -9
- data/assets/{include → platform/include}/mruby/endian.h +1 -1
- data/assets/platform/include/mruby/error.h +173 -0
- data/assets/platform/include/mruby/gc.h +79 -0
- data/assets/{include → platform/include}/mruby/hash.h +1 -7
- data/assets/platform/include/mruby/internal.h +282 -0
- data/assets/platform/include/mruby/irep.h +143 -0
- data/assets/{include → platform/include}/mruby/istruct.h +1 -1
- data/assets/platform/include/mruby/khash.h +455 -0
- data/assets/platform/include/mruby/mempool.h +19 -0
- data/assets/{include → platform/include}/mruby/numeric.h +7 -10
- data/assets/platform/include/mruby/object.h +51 -0
- data/assets/{include → platform/include}/mruby/opcode.h +5 -5
- data/assets/{include → platform/include}/mruby/ops.h +19 -6
- data/assets/platform/include/mruby/presym/id.h +1447 -0
- data/assets/{include → platform/include}/mruby/presym/scanning.h +10 -7
- data/assets/platform/include/mruby/presym/table.h +2893 -0
- data/assets/platform/include/mruby/presym.h +65 -0
- data/assets/platform/include/mruby/proc.h +184 -0
- data/assets/{include → platform/include}/mruby/range.h +0 -2
- data/assets/{include → platform/include}/mruby/string.h +33 -53
- data/assets/platform/include/mruby/throw.h +81 -0
- data/assets/{include → platform/include}/mruby/value.h +64 -29
- data/assets/{include → platform/include}/mruby/variable.h +6 -23
- data/assets/{include → platform/include}/mruby/version.h +7 -7
- data/assets/{include → platform/include}/mruby.h +238 -116
- data/assets/platform/macos-arm64/bin/mrbc +0 -0
- data/assets/platform/macos-arm64/lib/libSDL3.a +0 -0
- data/assets/platform/macos-arm64/lib/libSDL3_image.a +0 -0
- data/assets/platform/macos-arm64/lib/libSDL3_mixer.a +0 -0
- data/assets/platform/macos-arm64/lib/libSDL3_ttf.a +0 -0
- data/assets/platform/macos-arm64/lib/libmruby.a +0 -0
- data/assets/platform/wasm/lib/libFLAC.a +0 -0
- data/assets/platform/wasm/lib/libSDL3.a +0 -0
- data/assets/platform/wasm/lib/libSDL3_image.a +0 -0
- data/assets/platform/wasm/lib/libSDL3_mixer.a +0 -0
- data/assets/platform/wasm/lib/libSDL3_ttf.a +0 -0
- data/assets/platform/wasm/lib/libfreetype.a +0 -0
- data/assets/platform/wasm/lib/libharfbuzz.a +0 -0
- data/assets/platform/wasm/lib/libmruby.a +0 -0
- data/assets/platform/wasm/lib/libogg.a +0 -0
- data/assets/platform/wasm/lib/libplutosvg.a +0 -0
- data/assets/platform/wasm/lib/libplutovg.a +0 -0
- data/assets/platform/wasm/lib/libpng.a +0 -0
- data/assets/platform/wasm/lib/libpng16.a +0 -0
- data/assets/platform/wasm/lib/libvorbis.a +0 -0
- data/assets/platform/wasm/lib/libvorbisfile.a +0 -0
- data/assets/platform/wasm/lib/libzlibstatic.a +0 -0
- data/assets/platform/windows-arm64-mingw-ucrt/bin/mrbc.exe +0 -0
- data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3.a +0 -0
- data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3_image.a +0 -0
- data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3_mixer.a +0 -0
- data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3_ttf.a +0 -0
- data/assets/platform/windows-arm64-mingw-ucrt/lib/libmruby.a +0 -0
- data/assets/platform/windows-x86_64-mingw-ucrt/bin/mrbc.exe +0 -0
- data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3.a +0 -0
- data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3_image.a +0 -0
- data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3_mixer.a +0 -0
- data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3_ttf.a +0 -0
- data/assets/platform/windows-x86_64-mingw-ucrt/lib/libmruby.a +0 -0
- data/assets/resources/fonts/outfit/OFL.txt +93 -0
- data/assets/resources/fonts/outfit/outfit.ttf +0 -0
- data/assets/resources/fonts/roboto_mono/OFL.txt +91 -0
- data/assets/resources/fonts/roboto_mono/roboto_mono.ttf +0 -0
- data/assets/resources/icons/icon.icns +0 -0
- data/assets/resources/icons/icon.png +0 -0
- data/assets/resources/spritesheets/License.txt +28 -0
- data/assets/resources/spritesheets/spritesheet-backgrounds.png +0 -0
- data/assets/resources/spritesheets/spritesheet-backgrounds.xml +16 -0
- data/assets/resources/spritesheets/spritesheet-characters.png +0 -0
- data/assets/resources/spritesheets/spritesheet-characters.xml +47 -0
- data/assets/resources/spritesheets/spritesheet-enemies.png +0 -0
- data/assets/resources/spritesheets/spritesheet-enemies.xml +62 -0
- data/assets/resources/spritesheets/spritesheet-tiles.png +0 -0
- data/assets/resources/spritesheets/spritesheet-tiles.xml +316 -0
- data/assets/{wasm → resources/web}/template.html +1 -1
- data/assets/target.rb +131 -0
- data/bin/ruby2d +281 -82
- data/examples/astar.rb +269 -0
- data/examples/asteroids.rb +403 -0
- data/examples/bezier_editor.rb +96 -0
- data/examples/boids.rb +191 -0
- data/examples/bouncing_balls.rb +119 -0
- data/examples/breakout.rb +186 -0
- data/examples/constellations.rb +100 -0
- data/examples/dashboard.rb +133 -0
- data/examples/double_pendulum.rb +254 -0
- data/examples/falling_sand.rb +291 -0
- data/examples/fireworks.rb +110 -0
- data/examples/fluid_dynamics.rb +340 -0
- data/examples/fourier_epicycles.rb +142 -0
- data/examples/fractal_tree.rb +326 -0
- data/examples/game_of_life.rb +148 -0
- data/examples/gamepads.rb +333 -0
- data/examples/hill_driver.rb +613 -0
- data/examples/logo_animation.rb +251 -0
- data/examples/lorenz_attractor.rb +115 -0
- data/examples/mandelbrot.rb +207 -0
- data/examples/marching_squares.rb +200 -0
- data/examples/maze.rb +323 -0
- data/examples/nbody.rb +338 -0
- data/examples/outrun.rb +391 -0
- data/examples/pixel_paint.rb +313 -0
- data/examples/platformer.rb +335 -0
- data/examples/ray_casting_maze.rb +175 -0
- data/examples/shadow_casting.rb +151 -0
- data/examples/shape_recognizer.rb +908 -0
- data/examples/snake.rb +144 -0
- data/examples/sprite_sheets.rb +246 -0
- data/examples/swarm.rb +206 -0
- data/examples/tsp_annealing.rb +104 -0
- data/examples/ui_controls.rb +163 -0
- data/examples/wireframe_3d.rb +139 -0
- data/ext/ruby2d/audio.c +324 -0
- data/ext/ruby2d/canvas.c +1715 -494
- data/ext/ruby2d/ext.c +541 -0
- data/ext/ruby2d/extconf.rb +122 -145
- data/ext/ruby2d/font.c +566 -20
- data/ext/ruby2d/fps.c +92 -0
- data/ext/ruby2d/image.c +466 -41
- data/ext/ruby2d/ruby2d.c +374 -1890
- data/ext/ruby2d/ruby2d.h +840 -460
- data/ext/ruby2d/shapes.c +931 -101
- data/ext/ruby2d/text.c +586 -21
- data/ext/ruby2d/window.c +1693 -283
- data/lib/ruby2d/atlas_parser.rb +194 -0
- data/lib/ruby2d/audio.rb +73 -0
- data/lib/ruby2d/benchmark.rb +259 -0
- data/lib/ruby2d/bitmap_text.rb +155 -0
- data/lib/ruby2d/button.rb +402 -0
- data/lib/ruby2d/canvas.rb +703 -279
- data/lib/ruby2d/circle.rb +206 -29
- data/lib/ruby2d/cli/browser.rb +314 -0
- data/lib/ruby2d/cli/build.rb +471 -257
- data/lib/ruby2d/cli/colorize.rb +7 -5
- data/lib/ruby2d/cli/examples.rb +127 -0
- data/lib/ruby2d/cli/launch.rb +24 -39
- data/lib/ruby2d/cli/lib_files.rb +48 -0
- data/lib/ruby2d/cli/messages.rb +40 -0
- data/lib/ruby2d/cli/setup.rb +273 -0
- data/lib/ruby2d/cli/static_server.rb +160 -0
- data/lib/ruby2d/cli/usage.rb +255 -0
- data/lib/ruby2d/color.rb +191 -69
- data/lib/ruby2d/core.rb +37 -19
- data/lib/ruby2d/deps_help.rb +89 -0
- data/lib/ruby2d/dsl.rb +51 -12
- data/lib/ruby2d/ellipse.rb +228 -0
- data/lib/ruby2d/exceptions.rb +0 -2
- data/lib/ruby2d/font.rb +34 -74
- data/lib/ruby2d/gamepad.rb +323 -0
- data/lib/ruby2d/gem_paths.rb +19 -0
- data/lib/ruby2d/image.rb +155 -52
- data/lib/ruby2d/interactive.rb +103 -0
- data/lib/ruby2d/json_parser.rb +268 -0
- data/lib/ruby2d/line.rb +194 -85
- data/lib/ruby2d/mruby_compat.rb +12 -0
- data/lib/ruby2d/polygon.rb +297 -0
- data/lib/ruby2d/polyline.rb +368 -0
- data/lib/ruby2d/quad.rb +358 -94
- data/lib/ruby2d/rectangle.rb +77 -19
- data/lib/ruby2d/renderable.rb +411 -11
- data/lib/ruby2d/sprite.rb +471 -180
- data/lib/ruby2d/sprite_sheet.rb +64 -0
- data/lib/ruby2d/square.rb +29 -17
- data/lib/ruby2d/text.rb +196 -65
- data/lib/ruby2d/tileset.rb +139 -81
- data/lib/ruby2d/triangle.rb +324 -89
- data/lib/ruby2d/version.rb +1 -3
- data/lib/ruby2d/vertices.rb +62 -85
- data/lib/ruby2d/warnings.rb +29 -0
- data/lib/ruby2d/window/class_methods.rb +218 -0
- data/lib/ruby2d/window/gamepad_events.rb +141 -0
- data/lib/ruby2d/window/key_events.rb +74 -0
- data/lib/ruby2d/window/mouse_events.rb +171 -0
- data/lib/ruby2d/window/object_events.rb +168 -0
- data/lib/ruby2d/window.rb +632 -585
- data/lib/ruby2d.rb +14 -19
- metadata +275 -428
- data/assets/app.icns +0 -0
- data/assets/include/GLES2/gl2.h +0 -656
- data/assets/include/GLES2/gl2ext.h +0 -3949
- data/assets/include/GLES2/gl2ext_angle.h +0 -701
- data/assets/include/GLES2/gl2platform.h +0 -27
- data/assets/include/GLES3/gl3.h +0 -1192
- data/assets/include/GLES3/gl31.h +0 -1507
- data/assets/include/GLES3/gl32.h +0 -1808
- data/assets/include/GLES3/gl3platform.h +0 -27
- data/assets/include/KHR/khrplatform.h +0 -290
- data/assets/include/SDL2/SDL.h +0 -233
- data/assets/include/SDL2/SDL_assert.h +0 -326
- data/assets/include/SDL2/SDL_atomic.h +0 -415
- data/assets/include/SDL2/SDL_audio.h +0 -1500
- data/assets/include/SDL2/SDL_clipboard.h +0 -141
- data/assets/include/SDL2/SDL_config.h +0 -61
- data/assets/include/SDL2/SDL_config_android.h +0 -194
- data/assets/include/SDL2/SDL_config_emscripten.h +0 -218
- data/assets/include/SDL2/SDL_config_iphoneos.h +0 -217
- data/assets/include/SDL2/SDL_config_macosx.h +0 -277
- data/assets/include/SDL2/SDL_config_minimal.h +0 -95
- data/assets/include/SDL2/SDL_config_ngage.h +0 -89
- data/assets/include/SDL2/SDL_config_os2.h +0 -207
- data/assets/include/SDL2/SDL_config_pandora.h +0 -141
- data/assets/include/SDL2/SDL_config_windows.h +0 -331
- data/assets/include/SDL2/SDL_config_wingdk.h +0 -253
- data/assets/include/SDL2/SDL_config_winrt.h +0 -220
- data/assets/include/SDL2/SDL_config_xbox.h +0 -235
- data/assets/include/SDL2/SDL_cpuinfo.h +0 -594
- data/assets/include/SDL2/SDL_endian.h +0 -348
- data/assets/include/SDL2/SDL_error.h +0 -163
- data/assets/include/SDL2/SDL_events.h +0 -1166
- data/assets/include/SDL2/SDL_filesystem.h +0 -149
- data/assets/include/SDL2/SDL_gamecontroller.h +0 -1074
- data/assets/include/SDL2/SDL_gesture.h +0 -117
- data/assets/include/SDL2/SDL_guid.h +0 -100
- data/assets/include/SDL2/SDL_haptic.h +0 -1341
- data/assets/include/SDL2/SDL_hidapi.h +0 -451
- data/assets/include/SDL2/SDL_hints.h +0 -2569
- data/assets/include/SDL2/SDL_image.h +0 -2173
- data/assets/include/SDL2/SDL_joystick.h +0 -1066
- data/assets/include/SDL2/SDL_keyboard.h +0 -353
- data/assets/include/SDL2/SDL_keycode.h +0 -358
- data/assets/include/SDL2/SDL_loadso.h +0 -115
- data/assets/include/SDL2/SDL_log.h +0 -404
- data/assets/include/SDL2/SDL_main.h +0 -275
- data/assets/include/SDL2/SDL_mixer.h +0 -2784
- data/assets/include/SDL2/SDL_mouse.h +0 -465
- data/assets/include/SDL2/SDL_mutex.h +0 -471
- data/assets/include/SDL2/SDL_name.h +0 -33
- data/assets/include/SDL2/SDL_pixels.h +0 -644
- data/assets/include/SDL2/SDL_platform.h +0 -261
- data/assets/include/SDL2/SDL_quit.h +0 -58
- data/assets/include/SDL2/SDL_rect.h +0 -376
- data/assets/include/SDL2/SDL_render.h +0 -1919
- data/assets/include/SDL2/SDL_revision.h +0 -6
- data/assets/include/SDL2/SDL_rwops.h +0 -841
- data/assets/include/SDL2/SDL_sensor.h +0 -322
- data/assets/include/SDL2/SDL_shape.h +0 -155
- data/assets/include/SDL2/SDL_stdinc.h +0 -830
- data/assets/include/SDL2/SDL_surface.h +0 -997
- data/assets/include/SDL2/SDL_system.h +0 -623
- data/assets/include/SDL2/SDL_syswm.h +0 -386
- data/assets/include/SDL2/SDL_test_images.h +0 -78
- data/assets/include/SDL2/SDL_test_random.h +0 -115
- data/assets/include/SDL2/SDL_thread.h +0 -464
- data/assets/include/SDL2/SDL_timer.h +0 -222
- data/assets/include/SDL2/SDL_touch.h +0 -150
- data/assets/include/SDL2/SDL_ttf.h +0 -2316
- data/assets/include/SDL2/SDL_types.h +0 -29
- data/assets/include/SDL2/SDL_version.h +0 -204
- data/assets/include/SDL2/SDL_video.h +0 -2150
- data/assets/include/SDL2/SDL_vulkan.h +0 -215
- data/assets/include/SDL2/begin_code.h +0 -187
- data/assets/include/mruby/boxing_no.h +0 -58
- data/assets/include/mruby/class.h +0 -108
- data/assets/include/mruby/error.h +0 -147
- data/assets/include/mruby/gc.h +0 -94
- data/assets/include/mruby/irep.h +0 -147
- data/assets/include/mruby/khash.h +0 -284
- data/assets/include/mruby/object.h +0 -43
- data/assets/include/mruby/presym/disable.h +0 -70
- data/assets/include/mruby/presym/enable.h +0 -37
- data/assets/include/mruby/presym.h +0 -40
- data/assets/include/mruby/proc.h +0 -211
- data/assets/include/mruby/throw.h +0 -66
- data/assets/macos/universal/bin/mrbc +0 -0
- data/assets/macos/universal/lib/libFLAC.a +0 -0
- data/assets/macos/universal/lib/libSDL2.a +0 -0
- data/assets/macos/universal/lib/libSDL2_image.a +0 -0
- data/assets/macos/universal/lib/libSDL2_mixer.a +0 -0
- data/assets/macos/universal/lib/libSDL2_ttf.a +0 -0
- data/assets/macos/universal/lib/libavif.a +0 -0
- data/assets/macos/universal/lib/libbrotlicommon-static.a +0 -0
- data/assets/macos/universal/lib/libbrotlidec-static.a +0 -0
- data/assets/macos/universal/lib/libfreetype.a +0 -0
- data/assets/macos/universal/lib/libgraphite2.a +0 -0
- data/assets/macos/universal/lib/libharfbuzz.a +0 -0
- data/assets/macos/universal/lib/libhwy.a +0 -0
- data/assets/macos/universal/lib/libjpeg.a +0 -0
- data/assets/macos/universal/lib/libjxl.a +0 -0
- data/assets/macos/universal/lib/libmodplug.a +0 -0
- data/assets/macos/universal/lib/libmpg123.a +0 -0
- data/assets/macos/universal/lib/libmruby.a +0 -0
- data/assets/macos/universal/lib/libogg.a +0 -0
- data/assets/macos/universal/lib/libpng.a +0 -0
- data/assets/macos/universal/lib/libtiff.a +0 -0
- data/assets/macos/universal/lib/libvorbis.a +0 -0
- data/assets/macos/universal/lib/libvorbisfile.a +0 -0
- data/assets/macos/universal/lib/libwebp.a +0 -0
- data/assets/macos/universal/lib/libzstd.a +0 -0
- data/assets/test_media/README.md +0 -3
- data/assets/test_media/bitstream_vera/COPYRIGHT.txt +0 -124
- data/assets/test_media/bitstream_vera/vera.ttf +0 -0
- data/assets/test_media/boom.png +0 -0
- data/assets/test_media/coin.png +0 -0
- data/assets/test_media/colors.png +0 -0
- data/assets/test_media/controller.png +0 -0
- data/assets/test_media/dial.wav +0 -0
- data/assets/test_media/hero.png +0 -0
- data/assets/test_media/image.bmp +0 -0
- data/assets/test_media/image.jpg +0 -0
- data/assets/test_media/image.png +0 -0
- data/assets/test_media/music.flac +0 -0
- data/assets/test_media/music.mp3 +0 -0
- data/assets/test_media/music.ogg +0 -0
- data/assets/test_media/music.wav +0 -0
- data/assets/test_media/originals/boom.pxm +0 -0
- data/assets/test_media/originals/coin.pxm +0 -0
- data/assets/test_media/originals/controller.sketch +0 -0
- data/assets/test_media/originals/hero.pxm +0 -0
- data/assets/test_media/originals/image.pxm +0 -0
- data/assets/test_media/originals/music.caf +0 -0
- data/assets/test_media/originals/texture_atlas.pxm +0 -0
- data/assets/test_media/rondo_alla_turka.ogg +0 -0
- data/assets/test_media/sound.flac +0 -0
- data/assets/test_media/sound.mp3 +0 -0
- data/assets/test_media/sound.ogg +0 -0
- data/assets/test_media/sound.wav +0 -0
- data/assets/test_media/sprite_sheet.png +0 -0
- data/assets/test_media/texture_atlas.png +0 -0
- data/assets/wasm/libmruby.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/bin/mrbc.exe +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libFLAC.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libLerc.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_image.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_mixer.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_ttf.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlicommon.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlidec.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbz2.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libdeflate.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libfreetype.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libglew32.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libgraphite2.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libharfbuzz.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libhwy.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjbig.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjpeg.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjxl.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/liblzma.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmodplug.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmpg123.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmruby.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libogg.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopus.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopusfile.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libpng.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libsndfile.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libssp.a +0 -1
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libstdc++.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libtiff.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbis.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbisfile.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libwebp.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libz.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libzstd.a +0 -0
- data/assets/windows/mingw-w64-x86_64/bin/mrbc.exe +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libFLAC.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libLerc.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libSDL2.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libSDL2_image.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libSDL2_mixer.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libSDL2_ttf.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libbrotlicommon.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libbrotlidec.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libbz2.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libdeflate.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libfreetype.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libglew32.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libgraphite2.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libharfbuzz.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libhwy.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libjbig.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libjpeg.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libjxl.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/liblzma.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libmodplug.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libmpg123.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libmruby.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libogg.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libopus.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libopusfile.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libpng.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libsndfile.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libssp.a +0 -1
- data/assets/windows/mingw-w64-x86_64/lib/libstdc++.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libtiff.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libvorbis.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libvorbisfile.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libwebp.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libz.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libzstd.a +0 -0
- data/assets/xcode/ios/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -98
- data/assets/xcode/ios/Assets.xcassets/Contents.json +0 -6
- data/assets/xcode/ios/Base.lproj/LaunchScreen.storyboard +0 -27
- data/assets/xcode/ios/Info.plist +0 -43
- data/assets/xcode/ios/MRuby.framework/Headers/mrbconf.h +0 -143
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/array.h +0 -280
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_nan.h +0 -102
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_no.h +0 -56
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_word.h +0 -144
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/class.h +0 -97
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/common.h +0 -77
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/compile.h +0 -195
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/data.h +0 -75
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/debug.h +0 -67
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/dump.h +0 -196
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/error.h +0 -75
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/gc.h +0 -91
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/hash.h +0 -215
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/irep.h +0 -75
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/istruct.h +0 -47
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/khash.h +0 -274
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/numeric.h +0 -161
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/object.h +0 -44
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/opcode.h +0 -69
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/ops.h +0 -117
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/proc.h +0 -131
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/range.h +0 -49
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/re.h +0 -16
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/string.h +0 -444
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/throw.h +0 -55
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/value.h +0 -309
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/variable.h +0 -136
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/version.h +0 -110
- data/assets/xcode/ios/MRuby.framework/Headers/mruby.h +0 -1282
- data/assets/xcode/ios/MRuby.framework/Info.plist +0 -20
- data/assets/xcode/ios/MRuby.framework/MRuby +0 -0
- data/assets/xcode/ios/MyApp.xcodeproj/project.pbxproj +0 -368
- data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/xcshareddata/MyApp.xcscmblueprint +0 -30
- data/assets/xcode/ios/main.c +0 -1
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Contents.json +0 -17
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Contents.json +0 -17
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json +0 -32
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/LaunchImage.launchimage/Contents.json +0 -22
- data/assets/xcode/tvos/Info.plist +0 -30
- data/assets/xcode/tvos/MRuby.framework/Headers/mrbconf.h +0 -143
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/array.h +0 -280
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_nan.h +0 -102
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_no.h +0 -56
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_word.h +0 -144
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/class.h +0 -97
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/common.h +0 -77
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/compile.h +0 -195
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/data.h +0 -75
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/debug.h +0 -67
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/dump.h +0 -196
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/error.h +0 -75
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/gc.h +0 -91
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/hash.h +0 -215
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/irep.h +0 -75
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/istruct.h +0 -47
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/khash.h +0 -274
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/numeric.h +0 -161
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/object.h +0 -44
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/opcode.h +0 -69
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/ops.h +0 -117
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/proc.h +0 -131
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/range.h +0 -49
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/re.h +0 -16
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/string.h +0 -444
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/throw.h +0 -55
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/value.h +0 -309
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/variable.h +0 -136
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/version.h +0 -110
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby.h +0 -1282
- data/assets/xcode/tvos/MRuby.framework/Info.plist +0 -20
- data/assets/xcode/tvos/MRuby.framework/MRuby +0 -0
- data/assets/xcode/tvos/MyApp.xcodeproj/project.pbxproj +0 -350
- data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/xcshareddata/MyApp.xcscmblueprint +0 -30
- data/assets/xcode/tvos/main.c +0 -1
- data/ext/ruby2d/common.c +0 -185
- data/ext/ruby2d/controllers.c +0 -110
- data/ext/ruby2d/gl.c +0 -398
- data/ext/ruby2d/gl2.c +0 -86
- data/ext/ruby2d/gl3.c +0 -304
- data/ext/ruby2d/gles.c +0 -302
- data/ext/ruby2d/input.c +0 -48
- data/ext/ruby2d/music.c +0 -127
- data/ext/ruby2d/sound.c +0 -132
- data/lib/ruby2d/cli/console.rb +0 -65
- data/lib/ruby2d/cli/enable_console.rb +0 -7
- data/lib/ruby2d/cli/platform.rb +0 -17
- data/lib/ruby2d/music.rb +0 -77
- data/lib/ruby2d/pixel.rb +0 -18
- data/lib/ruby2d/pixmap.rb +0 -39
- data/lib/ruby2d/pixmap_atlas.rb +0 -56
- data/lib/ruby2d/sound.rb +0 -61
- data/lib/ruby2d/texture.rb +0 -38
- /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2.h +0 -0
- /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2ext.h +0 -0
- /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2platform.h +0 -0
- /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_khrplatform.h +0 -0
- /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
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
#
|
|
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],
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
@
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
#
|
|
65
|
-
#
|
|
66
|
-
def
|
|
67
|
-
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
#
|
|
75
|
-
#
|
|
76
|
-
#
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
#
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
#
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
#
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
|
|
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
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
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
|
-
|
|
262
|
-
|
|
263
|
-
|
|
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
|
-
#
|
|
267
|
-
#
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
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
|
-
|
|
281
|
-
|
|
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
|
-
#
|
|
287
|
-
#
|
|
288
|
-
#
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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
|
-
|
|
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
|
-
|
|
299
|
-
|
|
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
|
|
303
|
-
|
|
304
|
-
|
|
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
|
|
308
|
-
|
|
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
|
-
|
|
311
|
-
|
|
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
|