rb_sdl2 0.1.0 → 0.2.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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +69 -0
  3. data/README.md +15 -1
  4. data/lib/rb_sdl2/audio/audio.rb +162 -0
  5. data/lib/rb_sdl2/audio/audio_buffer.rb +12 -19
  6. data/lib/rb_sdl2/audio/audio_device.rb +17 -23
  7. data/lib/rb_sdl2/audio/audio_spec.rb +38 -6
  8. data/lib/rb_sdl2/audio/audio_spec_reader.rb +10 -0
  9. data/lib/rb_sdl2/clipboard.rb +31 -31
  10. data/lib/rb_sdl2/cpu_info.rb +34 -17
  11. data/lib/rb_sdl2/cursor.rb +105 -24
  12. data/lib/rb_sdl2/display.rb +16 -16
  13. data/lib/rb_sdl2/display_mode.rb +1 -1
  14. data/lib/rb_sdl2/error.rb +14 -3
  15. data/lib/rb_sdl2/errors.rb +7 -0
  16. data/lib/rb_sdl2/event/event.rb +130 -0
  17. data/lib/rb_sdl2/event/event_filter.rb +34 -70
  18. data/lib/rb_sdl2/event/event_pointer.rb +26 -0
  19. data/lib/rb_sdl2/event/event_queue.rb +97 -120
  20. data/lib/rb_sdl2/event/event_type.rb +147 -205
  21. data/lib/rb_sdl2/filesystem.rb +8 -9
  22. data/lib/rb_sdl2/hint.rb +26 -24
  23. data/lib/rb_sdl2/keyboard/keyboard.rb +50 -0
  24. data/lib/rb_sdl2/keyboard/mod_state.rb +68 -0
  25. data/lib/rb_sdl2/keyboard/state.rb +39 -0
  26. data/lib/rb_sdl2/message_box.rb +69 -102
  27. data/lib/rb_sdl2/mouse/global_mouse.rb +10 -3
  28. data/lib/rb_sdl2/mouse/mouse.rb +64 -0
  29. data/lib/rb_sdl2/mouse/mouse_button.rb +13 -11
  30. data/lib/rb_sdl2/mouse/mouse_class.rb +9 -17
  31. data/lib/rb_sdl2/mouse/mouse_wheel.rb +21 -37
  32. data/lib/rb_sdl2/mouse/relative_mouse.rb +15 -1
  33. data/lib/rb_sdl2/palette.rb +15 -11
  34. data/lib/rb_sdl2/pixel_format_enum.rb +87 -55
  35. data/lib/rb_sdl2/platform.rb +3 -1
  36. data/lib/rb_sdl2/power_info.rb +34 -23
  37. data/lib/rb_sdl2/rect.rb +7 -1
  38. data/lib/rb_sdl2/ref_count_pointer.rb +25 -10
  39. data/lib/rb_sdl2/rw_ops/rw_file.rb +19 -0
  40. data/lib/rb_sdl2/rw_ops/rw_memory.rb +18 -0
  41. data/lib/rb_sdl2/rw_ops/rw_object.rb +126 -0
  42. data/lib/rb_sdl2/rw_ops/rw_ops.rb +104 -0
  43. data/lib/rb_sdl2/rw_ops/rw_ops_pointer.rb +14 -0
  44. data/lib/rb_sdl2/sdl.rb +72 -21
  45. data/lib/rb_sdl2/sdl_pointer.rb +22 -0
  46. data/lib/rb_sdl2/surface/blend_mode.rb +41 -41
  47. data/lib/rb_sdl2/surface/pixel_format.rb +34 -33
  48. data/lib/rb_sdl2/surface.rb +280 -244
  49. data/lib/rb_sdl2/text_input.rb +21 -15
  50. data/lib/rb_sdl2/timer.rb +36 -22
  51. data/lib/rb_sdl2/version.rb +5 -3
  52. data/lib/rb_sdl2/video.rb +17 -5
  53. data/lib/rb_sdl2/window/accessor.rb +135 -0
  54. data/lib/rb_sdl2/window/display.rb +8 -8
  55. data/lib/rb_sdl2/window/flash.rb +22 -0
  56. data/lib/rb_sdl2/window/hit_test.rb +22 -43
  57. data/lib/rb_sdl2/window/shape.rb +55 -40
  58. data/lib/rb_sdl2/window/state.rb +178 -0
  59. data/lib/rb_sdl2/window/window.rb +149 -0
  60. data/lib/rb_sdl2.rb +79 -17
  61. data/rb_sdl2.gemspec +12 -4
  62. metadata +38 -37
  63. data/lib/rb_sdl2/audio/audio_allowed_changes.rb +0 -17
  64. data/lib/rb_sdl2/audio/audio_format.rb +0 -23
  65. data/lib/rb_sdl2/audio.rb +0 -132
  66. data/lib/rb_sdl2/cursor/color_cursor.rb +0 -19
  67. data/lib/rb_sdl2/cursor/cursor_class.rb +0 -24
  68. data/lib/rb_sdl2/cursor/cursor_pointer.rb +0 -12
  69. data/lib/rb_sdl2/cursor/default_cursor.rb +0 -18
  70. data/lib/rb_sdl2/cursor/system_cursor.rb +0 -45
  71. data/lib/rb_sdl2/event.rb +0 -161
  72. data/lib/rb_sdl2/keyboard/key_mod.rb +0 -37
  73. data/lib/rb_sdl2/keyboard/keyboard_state.rb +0 -34
  74. data/lib/rb_sdl2/keyboard.rb +0 -50
  75. data/lib/rb_sdl2/mouse/window_mouse.rb +0 -17
  76. data/lib/rb_sdl2/mouse.rb +0 -74
  77. data/lib/rb_sdl2/rw_ops/rw_operator.rb +0 -102
  78. data/lib/rb_sdl2/rw_ops.rb +0 -124
  79. data/lib/rb_sdl2/screen_saver.rb +0 -11
  80. data/lib/rb_sdl2/window/dialog.rb +0 -19
  81. data/lib/rb_sdl2/window/grab.rb +0 -23
  82. data/lib/rb_sdl2/window/position.rb +0 -38
  83. data/lib/rb_sdl2/window/size.rb +0 -59
  84. data/lib/rb_sdl2/window/window_flags.rb +0 -78
  85. data/lib/rb_sdl2/window.rb +0 -242
@@ -0,0 +1,104 @@
1
+ module RbSDL2
2
+ require_relative 'rw_file'
3
+ require_relative 'rw_memory'
4
+ require_relative 'rw_object'
5
+
6
+ class RWOps
7
+ class << self
8
+ def open(...)
9
+ rw = new(...)
10
+ return rw unless block_given?
11
+ begin
12
+ yield(rw)
13
+ ensure
14
+ rw.close
15
+ end
16
+ end
17
+
18
+ alias to_ptr new
19
+ end
20
+
21
+ def initialize(ptr)
22
+ @ptr = ptr
23
+ end
24
+
25
+ # close 呼び出しの結果によらずポインターは開放されます。
26
+ # 継承先のクラスは close をオーバーライドしてポインターを適切に扱う必要があります。
27
+ def close
28
+ # SDL_RWclose は必ずポインターを開放する。二重開放を防ぐ。
29
+ unless closed?
30
+ # クローズ処理は @ptr 先にあるメンバーの close 関数内あるため、SDL_RWclose() を呼ぶ。
31
+ err = ::SDL.RWclose(@ptr)
32
+ raise RbSDL2Error if err < 0
33
+ end
34
+ rescue => e
35
+ # Ruby IO と同じように例外を出さない。デバッグモードでは例外を出す。
36
+ raise e if $DEBUG
37
+ ensure
38
+ # ポインターは開放済みのためファイナライザーを停止させる。
39
+ @ptr.autorelease = false
40
+ @ptr = nil
41
+ end
42
+
43
+ def closed?
44
+ # @ptr があるのに autorelease? が false の場合はポインターが Ruby の外に渡されているだろう。
45
+ # この場合をクローズされたと判断する。
46
+ !@ptr&.autorelease?
47
+ end
48
+
49
+ def pos=(n)
50
+ seek(n, IO::SEEK_SET)
51
+ end
52
+
53
+ def read(length = nil)
54
+ raise IOError if closed?
55
+ len = length.nil? ? size - tell : length
56
+ raise ArgumentError if len < 0
57
+ return "" if len == 0
58
+ ptr = ::FFI::MemoryPointer.new(len)
59
+ num = ::SDL.RWread(@ptr, ptr, 1, len)
60
+ raise RbSDL2Error if num == 0
61
+ ptr.read_bytes(num)
62
+ end
63
+
64
+ def seek(offset, whence = IO::SEEK_SET)
65
+ raise IOError if closed?
66
+ raise RbSDL2Error if ::SDL.RWseek(@ptr, offset, whence) == -1
67
+ 0
68
+ end
69
+
70
+ def size
71
+ raise IOError if closed?
72
+ num = ::SDL.RWsize(@ptr)
73
+ raise RbSDL2Error if num < 0
74
+ num
75
+ end
76
+
77
+ def tell
78
+ raise IOError if closed?
79
+ num = ::SDL.RWtell(@ptr)
80
+ raise RbSDL2Error if num == -1
81
+ num
82
+ end
83
+ alias pos tell
84
+
85
+ # close メソッドを呼び出した後、インスタンスからポインターを取り出すことはできません。
86
+ def to_ptr
87
+ raise TypeError if closed?
88
+ @ptr
89
+ end
90
+
91
+ def write(*str)
92
+ raise FrozenError if frozen?
93
+ raise IOError if closed?
94
+ str.inject(0) do |sum, obj|
95
+ bytes = obj.to_s
96
+ len = bytes.size
97
+ ptr = ::FFI::MemoryPointer.new(len).write_bytes(bytes)
98
+ num = ::SDL.RWwrite(@ptr, ptr, 1, len)
99
+ raise RbSDL2Error if num < len
100
+ sum + len
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,14 @@
1
+ module RbSDL2
2
+ class RWOps
3
+ class RWOpsPointer < ::FFI::AutoPointer
4
+ class << self
5
+ def release(ptr)
6
+ # SDL_RWclose() は必ず(エラー時も) SDL_RWOps 構造体を開放する。
7
+ # 2重開放を防ぐため、手動でリソースを開放する場合はこのオブジェクトの free を呼び出すこと。
8
+ err = ::SDL.RWclose(ptr)
9
+ raise RbSDL2Error if err < 0
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
data/lib/rb_sdl2/sdl.rb CHANGED
@@ -1,32 +1,83 @@
1
1
  module RbSDL2
2
2
  module SDL
3
- module InitFlags
4
- class << self
5
- def to_num(audio: false, events: false, game_controller: false, haptic: false,
6
- joystick: false, sensor: false, timer: false, video: false)
7
- num = 0 |
8
- (audio ? ::SDL2::SDL_INIT_TIMER : 0) |
9
- (events ? ::SDL2::SDL_INIT_EVENTS : 0) |
10
- (game_controller ? ::SDL2::SDL_INIT_GAMECONTROLLER : 0) |
11
- (haptic ? ::SDL2::SDL_INIT_HAPTIC : 0) |
12
- (joystick ? ::SDL2::SDL_INIT_JOYSTICK : 0) |
13
- (sensor ? ::SDL2::SDL_INIT_SENSOR : 0) |
14
- (timer ? ::SDL2::SDL_INIT_TIMER : 0) |
15
- (video ? ::SDL2::SDL_INIT_VIDEO : 0)
16
- num == 0 ? ::SDL2::SDL_INIT_EVERYTHING : num
17
- end
18
- end
19
- end
3
+ SDL_INIT_TIMER = 0x00000001
4
+ SDL_INIT_AUDIO = 0x00000010
5
+ SDL_INIT_VIDEO = 0x00000020
6
+ SDL_INIT_JOYSTICK = 0x00000200
7
+ SDL_INIT_HAPTIC = 0x00001000
8
+ SDL_INIT_GAMECONTROLLER = 0x00002000
9
+ SDL_INIT_EVENTS = 0x00004000
10
+ SDL_INIT_SENSOR = 0x00008000
11
+
12
+ SDL_INIT_EVERYTHING = SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS |
13
+ SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_SENSOR
20
14
 
21
15
  class << self
22
- def init(**flags)
23
- err = ::SDL2.SDL_Init(InitFlags.to_num(**flags))
16
+ # SDL を初期化します。
17
+ # flags に起動したい SDL サブシステムのシンボルで指定します。
18
+ # flags を指定指定しない場合は全ての SDL サブシステムが起動します。
19
+ # SDL サブシステムのシンボルは
20
+ # :audio, :events, :game_controller, :haptic, :joystick, :sensor, :timer, :video
21
+ # です。
22
+ def init(*flags)
23
+ err = ::SDL.Init(to_num(*flags))
24
24
  raise RbSDL2Error if err < 0
25
25
  end
26
26
 
27
- def init?(**flags) = ::SDL2.SDL_WasInit(mask = InitFlags.to_num(**flags)) == mask
27
+ # SDL サブシステムが初期化されているか確認します。
28
+ # flags に与えたシンボルの SDL サブシステムが全て起動している時に true を戻します。
29
+ def init?(*flags) = ::SDL.WasInit(mask = to_num(*flags)) == mask
30
+
31
+ # SDL を終了します。RbSDL2 ではアプリケーションの終了時にこのメソッドを呼ぶ必要はありません。
32
+ # 終了後に再び SDL サブシステムを起動する必要がある場合は再度 init メソッドを呼ぶことができます。
33
+ # このメソッドは何度でも呼び出すことができます。
34
+ def quit = ::SDL.Quit
35
+
36
+ private def to_num(*flags)
37
+ flags.inject(0) { |num, sym|
38
+ num | case sym
39
+ when :audio then SDL_INIT_AUDIO
40
+ when :events then SDL_INIT_EVENTS
41
+ when :game_controller then SDL_INIT_GAMECONTROLLER
42
+ when :haptic then SDL_INIT_HAPTIC
43
+ when :joystick then SDL_INIT_JOYSTICK
44
+ when :sensor then SDL_INIT_SENSOR
45
+ when :timer then SDL_INIT_TIMER
46
+ when :video then SDL_INIT_VIDEO
47
+ else
48
+ raise ArgumentError, "Invalid sub system name(#{sym})"
49
+ end
50
+ }.nonzero? || SDL_INIT_EVERYTHING
51
+ end
52
+
53
+ # SDL String(C String, UTF-8) を Ruby String へ変換します。
54
+ # 戻り値の文字列エンコードは UTF-8 です。ptr へ与えたポインター先のメモリーは開放しません。
55
+ # ptr へ NULL ポインターを与えても安全です。その場合は空文字を戻します。
56
+ # 戻り値の文字列は Ruby 側へコピーされたものです。これを変更しても SDL のメモリー領域に影響を与えません。
57
+ def ptr_to_str(ptr)
58
+ if ptr.null?
59
+ ""
60
+ else
61
+ ptr.read_string.force_encoding(Encoding::UTF_8)
62
+ end
63
+ end
64
+
65
+ # 厳密な定義のためエンコーディングは ASCII-8BIT とする。
66
+ NUL = "\x00".encode!(Encoding::ASCII_8BIT).freeze
28
67
 
29
- def quit = ::SDL2.SDL_Quit
68
+ # Ruby String を SDL で取り扱う String へ変換します。
69
+ # 戻り値は UTF-8 エンコードされた変更不可能な文字列です。
70
+ # 内部では s へ与えた文字列をコピーし UTF-8 エンコードへ変換します。(元の文字列への影響はありません)
71
+ # 文字列に NUL 文字が含まれる場合は ArgumentError が発生します。
72
+ def str_to_sdl(s)
73
+ # dup -> UTF-8 -> ASCII-8BIT
74
+ # ASCII-8BIT にするのは size メソッドで正確なバイト数を得るため。(bytesize は忘れることがある)
75
+ # frozen にして SDL 用文字列を変更(例えばエンコーディング)させない。
76
+ sdl = String.new(s).encode!(Encoding::UTF_8).force_encoding(Encoding::ASCII_8BIT).freeze
77
+ # NUL 文字の混入チェック
78
+ raise ArgumentError if sdl.include?(NUL)
79
+ sdl
80
+ end
30
81
  end
31
82
  end
32
83
  end
@@ -0,0 +1,22 @@
1
+ module RbSDL2
2
+ # SDL のメモリーアロケーターで確保されたメモリー領域を表すクラスです。
3
+ # SDL 関数の戻り値がポインターで Ruby 側でメモリー開放が必要な時(例えば char ポインター)に使用します。
4
+ class SDLPointer < ::FFI::AutoPointer
5
+ class << self
6
+ def malloc(size)
7
+ ptr = ::SDL.calloc(1, size)
8
+ raise NoMemoryError if ptr.null?
9
+ new(ptr)
10
+ end
11
+
12
+ def from_string(s)
13
+ sdl = SDL.str_to_sdl(s)
14
+ malloc(sdl.bytesize + 1).write_string(sdl)
15
+ end
16
+
17
+ def release(ptr) = ::SDL.free(ptr)
18
+ end
19
+
20
+ def to_s = SDL.ptr_to_str(self)
21
+ end
22
+ end
@@ -1,41 +1,41 @@
1
- module RbSDL2
2
- class Surface
3
- module BlendMode
4
- class << self
5
- def to_num(obj)
6
- case obj
7
- when /\Aadd/ then ::SDL2::SDL_BLENDMODE_ADD
8
- when /\Aalpha/, /\Ablend/ then ::SDL2::SDL_BLENDMODE_BLEND
9
- when /\Amod/ then ::SDL2::SDL_BLENDMODE_MOD
10
- when /\Amul/ then ::SDL2::SDL_BLENDMODE_MUL
11
- when /\Anone/, /\Anormal/ then ::SDL2::SDL_BLENDMODE_NONE
12
- else
13
- obj.to_i
14
- end
15
- end
16
-
17
- def to_name(num)
18
- case num
19
- when ::SDL2::SDL_BLENDMODE_ADD then "additive"
20
- when ::SDL2::SDL_BLENDMODE_BLEND then "alpha"
21
- when ::SDL2::SDL_BLENDMODE_MOD then "modulate"
22
- when ::SDL2::SDL_BLENDMODE_MUL then "multiply"
23
- when ::SDL2::SDL_BLENDMODE_NONE then "normal"
24
- else
25
- ""
26
- end
27
- end
28
- end
29
-
30
- def additive_blend_mode? = ::SDL2::SDL_BLENDMODE_ADD == blend_mode
31
-
32
- def alpha_blend_mode? = ::SDL2::SDL_BLENDMODE_BLEND == blend_mode
33
-
34
- def modulate_blend_mode? = ::SDL2::SDL_BLENDMODE_MOD == blend_mode
35
-
36
- def multiply_blend_mode? = ::SDL2::SDL_BLENDMODE_MUL == blend_mode
37
-
38
- def normal_blend_mode? = ::SDL2::SDL_BLENDMODE_NONE == blend_mode
39
- end
40
- end
41
- end
1
+ module RbSDL2
2
+ class Surface
3
+ module BlendMode
4
+ class << self
5
+ def to_num(obj)
6
+ case obj
7
+ when /\Aadd/ then ::SDL::BLENDMODE_ADD
8
+ when /\Aalpha/, /\Ablend/ then ::SDL::BLENDMODE_BLEND
9
+ when /\Amod/ then ::SDL::BLENDMODE_MOD
10
+ when /\Amul/ then ::SDL::BLENDMODE_MUL
11
+ when /\Anone/, /\Anormal/ then ::SDL::BLENDMODE_NONE
12
+ else
13
+ obj.to_i
14
+ end
15
+ end
16
+
17
+ def to_name(num)
18
+ case num
19
+ when ::SDL::BLENDMODE_ADD then "additive"
20
+ when ::SDL::BLENDMODE_BLEND then "alpha"
21
+ when ::SDL::BLENDMODE_MOD then "modulate"
22
+ when ::SDL::BLENDMODE_MUL then "multiply"
23
+ when ::SDL::BLENDMODE_NONE then "normal"
24
+ else
25
+ ""
26
+ end
27
+ end
28
+ end
29
+
30
+ def additive_blend_mode? = ::SDL::BLENDMODE_ADD == blend_mode
31
+
32
+ def alpha_blend_mode? = ::SDL::BLENDMODE_BLEND == blend_mode
33
+
34
+ def modulate_blend_mode? = ::SDL::BLENDMODE_MOD == blend_mode
35
+
36
+ def multiply_blend_mode? = ::SDL::BLENDMODE_MUL == blend_mode
37
+
38
+ def normal_blend_mode? = ::SDL::BLENDMODE_NONE == blend_mode
39
+ end
40
+ end
41
+ end
@@ -5,37 +5,34 @@ module RbSDL2
5
5
 
6
6
  class PixelFormatPointer < RefCountPointer
7
7
  class << self
8
- def release(ptr) = ::SDL2.SDL_FreeFormat(ptr)
8
+ def release(ptr) = ::SDL.FreeFormat(ptr)
9
9
 
10
- def entity_class = ::SDL2::SDL_PixelFormat
10
+ def entity_class = ::SDL::PixelFormat
11
11
  end
12
12
  end
13
13
 
14
14
  class << self
15
- require_relative '../pixel_format_enum'
16
-
17
- def new(format)
18
- ptr = PixelFormatPointer.new(::SDL2::SDL_AllocFormat(PixelFormatEnum.to_num(format)))
19
- raise RbSDL2Error if ptr.null?
20
- super(ptr)
21
- end
22
-
23
- def to_ptr(ptr)
24
- obj = allocate
25
- obj.__send__(:initialize, PixelFormatPointer.to_ptr(ptr))
26
- obj
27
- end
15
+ # アプリケーションが PixelFormat を作成する必要がないためコンストラクターを実装しない。
16
+ # FFI::AutoPointer によるポインター管理を行っているのは Surface 側で PixelFormat を公開しているため。
28
17
  end
29
18
 
30
19
  def initialize(ptr)
31
- @st = ::SDL2::SDL_PixelFormat.new(ptr)
20
+ @st = ::SDL::PixelFormat.new(PixelFormatPointer.to_ptr(ptr))
32
21
  end
33
22
 
34
23
  def ==(other)
35
- other.respond_to?(:to_ptr) && to_ptr == other.to_ptr
24
+ other.respond_to?(:to_ptr) && other.to_ptr == to_ptr
36
25
  end
37
26
 
38
- def alpha_mask? = @st[:Amask] > 0
27
+ def a_mask = @st[:Amask]
28
+
29
+ def b_mask = @st[:Bmask]
30
+
31
+ def g_mask = @st[:Gmask]
32
+
33
+ def r_mask = @st[:Rmask]
34
+
35
+ def a_mask? = @st[:Amask] > 0
39
36
 
40
37
  def bits_per_pixel = @st[:BitsPerPixel]
41
38
  alias bpp bits_per_pixel
@@ -50,37 +47,41 @@ module RbSDL2
50
47
  # indexed format のときはパレット番号を戻す。
51
48
  def pack_color(color)
52
49
  r, g, b, a = color
53
- if alpha_mask?
54
- ::SDL2.SDL_MapRGBA(self, r, g, b, a || ::SDL2::SDL_ALPHA_OPAQUE)
50
+ if a_mask?
51
+ ::SDL.MapRGBA(self, r, g, b, a || ::SDL::ALPHA_OPAQUE)
55
52
  else
56
- ::SDL2.SDL_MapRGB(self, r, g, b)
53
+ ::SDL.MapRGB(self, r, g, b)
57
54
  end
58
55
  end
59
56
 
60
57
  require_relative '../palette'
61
58
 
59
+ # パレットがある場合は Palette インスタンスを戻します。ない場合は nil を戻します。
62
60
  def palette
63
- # パレットは参照カウンターで生存の保証がある。
64
- # Ruby 側がパレットを保持している限り同一アドレスに違うパレットが作成されることはない。
65
- # SDL では PixelFormat の palette メンバーは(行儀よく SDL_SetPixelFormatPalette を使う場合は)
66
- # 後から NULL に書き換わることはない。
67
- (ptr = @st[:palette]) == @palette&.to_ptr ? @palette : @palette = Palette.to_ptr(ptr)
61
+ Palette.to_ptr(@st[:palette]) unless @st[:palette].null?
68
62
  end
69
63
 
70
64
  def palette=(pal)
71
- err = ::SDL2.SDL_SetPixelFormatPalette(self, pal)
72
- raise RbSDL2Error if err < 0
73
- @palette = nil
65
+ # SDL_SetPixelFormatPalette() はパレット・ポインターが NULL かどうかチェックしていない。
66
+ if Palette === pal && !pal.to_ptr.null?
67
+ err = ::SDL.SetPixelFormatPalette(self, pal)
68
+ raise RbSDL2Error if err < 0
69
+ else
70
+ raise ArgumentError, "pointer is NULL"
71
+ end
74
72
  end
75
73
 
74
+ def palette? = !@st[:palette].null?
75
+
76
76
  def to_ptr = @st.to_ptr
77
77
 
78
78
  # indexed format のときはパレット番号を引数へ与える。
79
- def unpack_color(pixel)
80
- if alpha_mask?
81
- ::SDL2.SDL_GetRGBA(pixel, self, *Array.new(4) { ::FFI::MemoryPointer.new(:uint8) })
79
+ def unpack_pixel(num)
80
+ color = Array.new(a_mask? ? 4 : 3) { ::FFI::MemoryPointer.new(:uint8) }
81
+ if a_mask?
82
+ ::SDL.GetRGBA(num, self, *color)
82
83
  else
83
- ::SDL2.SDL_GetRGB(pixel, self, *Array.new(3) { ::FFI::MemoryPointer.new(:uint8) })
84
+ ::SDL.GetRGB(num, self, *color)
84
85
  end
85
86
  color.map(&:read_uint8)
86
87
  end