rb_sdl2 0.1.2 → 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 +31 -0
  3. data/README.md +1 -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 +11 -4
  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 +12 -12
  34. data/lib/rb_sdl2/pixel_format_enum.rb +87 -55
  35. data/lib/rb_sdl2/platform.rb +1 -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 +67 -28
  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 -265
  49. data/lib/rb_sdl2/text_input.rb +21 -15
  50. data/lib/rb_sdl2/timer.rb +36 -31
  51. data/lib/rb_sdl2/version.rb +3 -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 +4 -4
  62. metadata +31 -35
  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 -105
  78. data/lib/rb_sdl2/rw_ops.rb +0 -149
  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
@@ -1,265 +1,280 @@
1
- module RbSDL2
2
- class Surface
3
- require_relative 'ref_count_pointer'
4
-
5
- class SurfacePointer < RefCountPointer
6
- class << self
7
- def release(ptr)
8
- # 備考:SDL では参照カウンターを操作する際にロックを行っていない。
9
- #
10
- # SDL_Surface ポインターの参照カウンターの扱いでは SDL_DONTFREE フラグを考慮する必要がある。
11
- # SDL_DONTFREE フラグが設定されていると SDL_FreeSurface を呼び出しても参照カウントが減少しない。
12
- # SDL_DONTFREE フラグの状態に関わらず Ruby 側ではポインターを正しく扱えるので参照カウントを増減する。
13
- # 備考:Window から SDL_Surface ポインターを取り出す際にこのフラグが設定されている。
14
- st = entity_class.new(ptr)
15
- if st[:flags] & ::SDL2::SDL_DONTFREE != 0
16
- st[:refcount] -= 1
17
- # SDL_DONTFREE が設定されているので参照カウントの値によらず SDL_FreeSurface を呼び出さない。
18
- # スレッドでの競合によりポインターを開放されない可能性(=メモリーリーク)はある。
19
- # 具体的にはこのセクションを実行中に SDL_EventPump が実行され、ウィンドウのリサイズ・イベントが発生
20
- # したときに起きる。この競合が起きないようにアプリケーションを実装する必要がある。
21
- else
22
- ::SDL2.SDL_FreeSurface(ptr)
23
- end
24
- end
25
-
26
- def entity_class = ::SDL2::SDL_Surface
27
- end
28
- end
29
-
30
- require_relative 'pixel_format_enum'
31
-
32
- class << self
33
- # 指定した Surface オブジェクトを基に指定した画像フォーマットの新しい Surface オブジェクトを柵瀬します。
34
- # surface へ変換元の Surface オブジェクトを与えます。
35
- # new_format へ変換先の画像フォーマット(PixelFormatEnumの名前か番号)を与えます。
36
- # 変換ができない場合は例外(RbSDL2::RbSDL2Error)を発生させます。
37
- # INDEX1*, INDEX4*, ARGB2101010、FOURCC系への変換はできません。
38
- # 変換先がインデックスカラー(INDEX8)の時は例外は発生しませんが期待する変換は行われません。
39
- # その時はサーフェィス全面がインデックス番号0で埋められています。
40
- def convert(surface, new_format)
41
- ptr = SurfacePointer.new(
42
- ::SDL2.SDL_ConvertSurfaceFormat(surface, PixelFormatEnum.to_num(new_format), 0))
43
- raise RbSDL2Error if ptr.null?
44
- obj = allocate
45
- obj.__send__(:initialize, ptr)
46
- obj
47
- end
48
-
49
- require_relative 'rw_ops'
50
-
51
- # ファイルから画像を読み込み新たな Surface オブジェクトを生成します。
52
- # file へ読み込む画像ファイルのパスを与えます。
53
- # 対応する画像は BMP 形式のみです。
54
- # 読み込みができない場合は例外(RbSDL2::RbSDL2Error)を発生させます。
55
- # インデックスカラー(2色、16色)は INDEX8 フォーマットとして読み込まれます。
56
- def load(file) = RWOps.new(file, "rb") { |rw| load_rw(rw) }
57
-
58
- # RWOps から画像を読み込み新たな Surface オブジェクトを生成します。
59
- # rw RbSDL2::RWOps オブジェクトか SDL_RWOps ポインターを与えます。
60
- # 読み込みができない場合は例外(RbSDL2::RbSDL2Error)を発生させます。
61
- # このメソッドは与えられたオブジェクトをクローズしません。
62
- def load_rw(rw)
63
- ptr = SurfacePointer.new(::SDL2.SDL_LoadBMP_RW(rw, 0))
64
- raise RbSDL2Error if ptr.null?
65
- obj = allocate
66
- obj.__send__(:initialize, ptr)
67
- obj
68
- end
69
-
70
- # 新しい Surface オブジェクトを生成します。
71
- # w へ画像の幅ピクセル数
72
- # h へ画像の縦ピクセル数
73
- # format へ画像フォーマット(PixelFormatEnumの名前か番号)を与えます。
74
- def new(w, h, format)
75
- ptr = SurfacePointer.new(
76
- ::SDL2.SDL_CreateRGBSurfaceWithFormat(0, w, h, 0, PixelFormatEnum.to_num(format)))
77
- raise RbSDL2Error if ptr.null?
78
- super(ptr)
79
- end
80
-
81
- # ポインターから Surface オブジェクトを生成します。
82
- # ptr へ対象となるポインターを与えます。
83
- # このメソッドは SDL_Surface 構造体の参照カウンターをサポートしています。
84
- # 生成した Surface オブジェクトは SDL 側で破棄しても Ruby 側のスコープに存在していれば安全に使用できます。
85
- def to_ptr(ptr)
86
- obj = allocate
87
- obj.__send__(:initialize, SurfacePointer.to_ptr(ptr))
88
- obj
89
- end
90
-
91
- def yuv_conversion_mode_name
92
- case ::SDL2.SDL_GetYUVConversionMode
93
- when ::SDL2::SDL_YUV_CONVERSION_JPEG then "JPEG"
94
- when ::SDL2::SDL_YUV_CONVERSION_BT601 then "BT601"
95
- when ::SDL2::SDL_YUV_CONVERSION_BT709 then "BT709"
96
- when ::SDL2::SDL_YUV_CONVERSION_AUTOMATIC then "AUTOMATIC"
97
- else ""
98
- end
99
- end
100
-
101
- def yuv_conversion_mode=(mode)
102
- ::SDL2.SDL_SetYUVConversionMode(mode)
103
- end
104
- end
105
-
106
- def initialize(ptr)
107
- @st = ::SDL2::SDL_Surface.new(ptr)
108
- end
109
-
110
- def ==(other)
111
- other.respond_to?(:to_ptr) && to_ptr == other.to_ptr
112
- end
113
-
114
- def alpha_mod
115
- alpha = ::FFI::MemoryPointer.new(:uint8)
116
- num = ::SDL2.SDL_GetSurfaceAlphaMod(self, alpha)
117
- raise RbSDL2Error if num < 0
118
- alpha.read_uint8
119
- end
120
-
121
- def alpha_mod=(alpha)
122
- num = ::SDL2.SDL_SetSurfaceAlphaMod(self, alpha)
123
- raise RbSDL2Error if num < 0
124
- end
125
-
126
- def blend_mode
127
- blend = ::FFI::MemoryPointer.new(:int)
128
- err = ::SDL2.SDL_GetSurfaceBlendMode(self, blend)
129
- raise RbSDL2Error if err < 0
130
- blend.read_int
131
- end
132
-
133
- require_relative 'surface/blend_mode'
134
- include BlendMode
135
-
136
- def blend_mode_name = BlendMode.to_name(blend_mode)
137
-
138
- def blend_mode=(blend)
139
- err = ::SDL2.SDL_SetSurfaceBlendMode(self, BlendMode.to_num(blend))
140
- raise RbSDL2Error if err < 0
141
- end
142
-
143
- def blit(other, from: nil, to: nil, scale: false)
144
- from &&= Rect.new(*from)
145
- to &&= Rect.new(*to)
146
- err = if scale
147
- ::SDL2.SDL_UpperBlitScaled(other, from, self, to)
148
- else
149
- ::SDL2.SDL_UpperBlit(other, from, self, to)
150
- end
151
- raise RbSDL2Error if err < 0
152
- end
153
-
154
- def bounds = [0, 0, w, h]
155
-
156
- def bytesize = pitch * height
157
-
158
- def clip
159
- rect = Rect.new
160
- ::SDL2.SDL_GetClipRect(self, rect)
161
- rect.to_a
162
- end
163
-
164
- # nil の場合はサーフェィス全域がクリップになる。
165
- def clip=(rect)
166
- rect &&= Rect.new(*rect)
167
- bool = ::SDL2.SDL_SetClipRect(self, rect)
168
- raise "out of bounds" if bool == ::SDL2::SDL_FALSE
169
- end
170
-
171
- def clear(color = [0, 0, 0, 0]) = fill(bounds, color)
172
-
173
- def color_key
174
- return unless color_key?
175
- key = ::FFI::MemoryPointer.new(:uint32)
176
- err = ::SDL2.SDL_GetColorKey(self, key)
177
- return RbSDL2Error if err < 0
178
- pixel_format.unpack_color(key.read_uint32)
179
- end
180
-
181
- def color_key=(color)
182
- err = if color
183
- ::SDL2.SDL_SetColorKey(self, ::SDL2::SDL_TRUE, pixel_format.pack_color(color))
184
- else
185
- ::SDL2.SDL_SetColorKey(self, ::SDL2::SDL_FALSE, 0)
186
- end
187
- raise RbSDL2Error if err < 0
188
- end
189
-
190
- def color_key? = ::SDL2.SDL_HasColorKey(self) == ::SDL2::SDL_TRUE
191
-
192
- def color_mod
193
- rgb = Array.new(3) { ::FFI::MemoryPointer.new(:uint8) }
194
- err = ::SDL2.SDL_GetSurfaceColorMod(self, *rgb)
195
- raise RbSDL2Error if err < 0
196
- rgb.map(&:read_uint8)
197
- end
198
-
199
- def color_mod=(color)
200
- r, g, b = color
201
- err = ::SDL2.SDL_SetSurfaceColorMod(self, r, g, b)
202
- raise RbSDL2Error if err < 0
203
- end
204
-
205
- def convert(new_format = format) = Surface.convert(self, new_format)
206
-
207
- def fill(rect = clip, color = [0, 0, 0, 0])
208
- err = ::SDL2.SDL_FillRect(self, Rect.new(*rect), pixel_format.pack_color(color))
209
- raise RbSDL2Error if err < 0
210
- end
211
-
212
- def height = @st[:h]
213
-
214
- alias h height
215
-
216
- def pitch = @st[:pitch]
217
-
218
- require_relative 'surface/pixel_format'
219
-
220
- def pixel_format
221
- # SDL_Surface の format メンバーは読み取り専用である。作成時の値が不変であることを前提としている。
222
- @pixel_format ||= PixelFormat.to_ptr(@st[:format])
223
- end
224
-
225
- require 'forwardable'
226
- extend Forwardable
227
- def_delegators :pixel_format, *%i(bits_per_pixel bpp format palette palette=)
228
-
229
- require_relative 'pixel_format_enum'
230
- include PixelFormatEnum
231
-
232
- def rle=(bool)
233
- err = ::SDL2.SDL_SetSurfaceRLE(self, bool ? 1 : 0)
234
- raise RbSDL2Error if err < 0
235
- end
236
-
237
- def rle? = ::SDL2.SDL_HasSurfaceRLE(self) == ::SDL2::SDL_TRUE
238
-
239
- require_relative 'rw_ops'
240
-
241
- def save(file) = RWOps.new(file, "wb") { |rw| save_rw(rw); nil }
242
-
243
- # save_rw は与えられたオブジェクトをオートクローズしません。
244
- def save_rw(rw)
245
- err = ::SDL2.SDL_SaveBMP_RW(rw, 0)
246
- raise RbSDL2Error if err < 0
247
- rw
248
- end
249
-
250
- def size = [width, height]
251
-
252
- def synchronize
253
- ::SDL2.SDL_LockSurface(self)
254
- yield(self)
255
- ensure
256
- ::SDL2.SDL_UnlockSurface(self)
257
- end
258
-
259
- def to_ptr = @st.to_ptr
260
-
261
- def width = @st[:w]
262
-
263
- alias w width
264
- end
265
- end
1
+ module RbSDL2
2
+ class Surface
3
+ require_relative 'ref_count_pointer'
4
+
5
+ class SurfacePointer < RefCountPointer
6
+ class << self
7
+ def dontfree?(ptr) = ptr.read_uint32 & ::SDL::DONTFREE != 0
8
+
9
+ def entity_class = ::SDL::Surface
10
+
11
+ def release(ptr)
12
+ unless ptr.null?
13
+ if dontfree?(ptr)
14
+ # SDL_DONTFREE が設定されている場合、SDL_FreeSurface() は参照カウントを減少しない。
15
+ # Ruby はポインターを正しく扱えるので参照カウントを減ずる。
16
+ # 備考:Window から Surface ポインターを取り出す際にこのフラグが設定されている。
17
+ dec_ref(ptr)
18
+ else
19
+ ::SDL.FreeSurface(ptr)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ require_relative 'pixel_format_enum'
27
+ require_relative 'rw_ops/rw_ops'
28
+
29
+ class << self
30
+ # 指定した Surface オブジェクトを基に指定した画像フォーマットの新しい Surface オブジェクトを柵瀬します。
31
+ # surface へ変換元の Surface オブジェクトを与えます。
32
+ # new_format へ変換先の画像フォーマット(PixelFormatEnumの名前か番号)を与えます。
33
+ # 変換ができない場合は例外(RbSDL2::RbSDL2Error)を発生させます。
34
+ # INDEX1*, INDEX4*, ARGB2101010、FOURCC系への変換はできません。
35
+ # 変換先がインデックスカラー(INDEX8)の時は例外は発生しませんが期待する変換は行われません。
36
+ # その時はサーフェィス全面がインデックス番号0で埋められています。
37
+ def convert(surface, new_format)
38
+ ptr = SurfacePointer.new(
39
+ ::SDL.ConvertSurfaceFormat(surface, PixelFormatEnum.to_num(new_format), 0))
40
+ raise RbSDL2Error if ptr.null?
41
+ obj = allocate
42
+ obj.__send__(:initialize, ptr)
43
+ obj
44
+ end
45
+
46
+ # ファイルから画像を読み込み新たな Surface オブジェクトを生成します。
47
+ # 読み込みに対応する画像は BMP 形式のみです。
48
+ # インデックスカラー(2色、16色)は INDEX8 フォーマット(256色)として読み込まれます。
49
+ # 読み込みができない場合は例外(RbSDL2Error)を発生させます。
50
+ #
51
+ # obj には ファイルへのパス(文字列)、オブジェクトを与えることができます。
52
+ # 例: File.open("path.bmp", "rb") { |f| Surface.load(f) }
53
+ # パスを与えた場合、読み込み後にクローズします。
54
+ # オブジェクトを与えた場合、それをクローズしません。
55
+ # SDL は読み込み時に IO::SEEK_SET によるシークを行います。
56
+ def load(obj)
57
+ RbSDL2.open_rw(obj) do |rw|
58
+ ptr = SurfacePointer.new(::SDL.LoadBMP_RW(rw, 0))
59
+ raise RbSDL2Error if ptr.null?
60
+ allocate.tap { |surface| surface.__send__(:initialize, ptr) }
61
+ end
62
+ end
63
+
64
+ # 新しい Surface オブジェクトを生成します。
65
+ # w は画像の幅ピクセル数
66
+ # h は画像の縦ピクセル数
67
+ # format は画像フォーマットのを表すシンボルを与えます。
68
+ # format へ FOURCC 系の画像フォーマットを与えた場合は例外を戻します。
69
+ def new(w, h, format)
70
+ ptr = SurfacePointer.new(
71
+ ::SDL.CreateRGBSurfaceWithFormat(0, w, h, 0, PixelFormatEnum.to_num(format)))
72
+ raise RbSDL2Error if ptr.null?
73
+ super(ptr)
74
+ end
75
+
76
+ # ポインターから Surface オブジェクトを生成します。
77
+ # ptr へ対象となるポインターを与えます。
78
+ # このメソッドは Surface 構造体の参照カウンターをサポートしています。
79
+ # 生成した Surface オブジェクトは SDL 側で破棄しても Ruby 側のスコープに存在していれば安全に使用できます。
80
+ def to_ptr(ptr)
81
+ obj = allocate
82
+ obj.__send__(:initialize, SurfacePointer.to_ptr(ptr))
83
+ obj
84
+ end
85
+ end
86
+
87
+ def initialize(ptr)
88
+ @st = ::SDL::Surface.new(ptr)
89
+ end
90
+
91
+ def ==(other)
92
+ other.respond_to?(:to_ptr) && other.to_ptr == to_ptr
93
+ end
94
+
95
+ def alpha_mod
96
+ alpha = ::FFI::MemoryPointer.new(:uint8)
97
+ num = ::SDL.GetSurfaceAlphaMod(self, alpha)
98
+ raise RbSDL2Error if num < 0
99
+ alpha.read_uint8
100
+ end
101
+
102
+ def alpha_mod=(alpha)
103
+ num = ::SDL.SetSurfaceAlphaMod(self, alpha)
104
+ raise RbSDL2Error if num < 0
105
+ end
106
+
107
+ def blend_mode
108
+ blend = ::FFI::MemoryPointer.new(:int)
109
+ err = ::SDL.GetSurfaceBlendMode(self, blend)
110
+ raise RbSDL2Error if err < 0
111
+ blend.read_int
112
+ end
113
+
114
+ require_relative 'surface/blend_mode'
115
+ include BlendMode
116
+
117
+ def blend_mode_name = BlendMode.to_name(blend_mode)
118
+
119
+ def blend_mode=(blend)
120
+ err = ::SDL.SetSurfaceBlendMode(self, BlendMode.to_num(blend))
121
+ raise RbSDL2Error if err < 0
122
+ end
123
+
124
+ def blit(other, from: nil, to: nil, scale: false)
125
+ from &&= Rect.new(*from)
126
+ to &&= Rect.new(*to)
127
+ err = if scale
128
+ ::SDL.UpperBlitScaled(other, from, self, to)
129
+ else
130
+ ::SDL.UpperBlit(other, from, self, to)
131
+ end
132
+ raise RbSDL2Error if err < 0
133
+ end
134
+
135
+ def bounds = [0, 0, w, h]
136
+
137
+ def bytesize = pitch * height
138
+
139
+ def clip
140
+ rect = Rect.new
141
+ ::SDL.GetClipRect(self, rect)
142
+ rect.to_a
143
+ end
144
+
145
+ # nil の場合はサーフェィス全域がクリップになる。
146
+ def clip=(rect)
147
+ rect &&= Rect.new(*rect)
148
+ bool = ::SDL.SetClipRect(self, rect)
149
+ raise "out of bounds" if bool == ::SDL::FALSE
150
+ end
151
+
152
+ def clear(color = [0, 0, 0, 0]) = fill(bounds, color)
153
+
154
+ def color_key
155
+ return unless color_key?
156
+ key = ::FFI::MemoryPointer.new(:uint32)
157
+ err = ::SDL.GetColorKey(self, key)
158
+ return RbSDL2Error if err < 0
159
+ pixel_format.unpack_color(key.read_uint32)
160
+ end
161
+
162
+ def color_key=(color)
163
+ err = if color
164
+ ::SDL.SetColorKey(self, ::SDL::TRUE, pixel_format.pack_color(color))
165
+ else
166
+ ::SDL.SetColorKey(self, ::SDL::FALSE, 0)
167
+ end
168
+ raise RbSDL2Error if err < 0
169
+ end
170
+
171
+ def color_key? = ::SDL.HasColorKey(self) == ::SDL::TRUE
172
+
173
+ def color_mod
174
+ rgb = Array.new(3) { ::FFI::MemoryPointer.new(:uint8) }
175
+ err = ::SDL.GetSurfaceColorMod(self, *rgb)
176
+ raise RbSDL2Error if err < 0
177
+ rgb.map(&:read_uint8)
178
+ end
179
+
180
+ def color_mod=(color)
181
+ r, g, b = color
182
+ err = ::SDL.SetSurfaceColorMod(self, r, g, b)
183
+ raise RbSDL2Error if err < 0
184
+ end
185
+
186
+ def convert(new_format = format) = Surface.convert(self, new_format)
187
+
188
+ def fill(rect = clip, color = [0, 0, 0, 0])
189
+ err = ::SDL.FillRect(self, Rect.new(*rect), pixel_format.pack_color(color))
190
+ raise RbSDL2Error if err < 0
191
+ end
192
+
193
+ def height = @st[:h]
194
+
195
+ alias h height
196
+
197
+ def pitch = @st[:pitch]
198
+
199
+ # 指定位置のピクセル・カラーを戻します。
200
+ def pixel_color(x, y) = unpack_pixel(pixel(x, y))
201
+
202
+ # 指定位置のピクセル値を戻します。
203
+ def pixel(x, y)
204
+ raise ArgumentError if x < 0 || width <= x
205
+ raise ArgumentError if y < 0 || height <= y
206
+
207
+ # RLE の場合にビットマップ・メモリーへアクセスするため synchronize が必要になる。
208
+ synchronize do
209
+ ptr = @st[:pixels] + (pitch * y + bytes_per_pixel * x)
210
+ case bytes_per_pixel
211
+ when 1 then ptr.read_uint8
212
+ when 2 then ptr.read_uint16
213
+ when 3 then ptr.read_uint32 & 0x1000000 # for little endian
214
+ when 4 then ptr.read_uint32
215
+ else
216
+ raise TypeError
217
+ end
218
+ end
219
+ end
220
+
221
+ require_relative 'surface/pixel_format'
222
+
223
+ # NOTE: @pixel_format へのアクセスは非公開にする予定です。
224
+ def pixel_format
225
+ # SDL_Surface の format メンバーは読み取り専用である。作成時の値が不変であることを前提とする。
226
+ # PixelFormat は参照カウンターで管理されている。
227
+ # 自身を所有している Surface が生きていればリソースが開放されることはない。
228
+ # PixelFormat は Index 系(5種)のみ個別にリソースが確保されている。
229
+ # RGB 系は SDL 側でキャッシュがあればそれを、なければ新しくリソースを確保している。
230
+ @pixel_format ||= PixelFormat.new(@st[:format])
231
+ end
232
+
233
+ require 'forwardable'
234
+ extend Forwardable
235
+ def_delegators :pixel_format,
236
+ *%i(a_mask a_mask? b_mask g_mask r_mask
237
+ bits_per_pixel bpp bytes_per_pixel format pack_color
238
+ palette palette= palette? unpack_pixel)
239
+
240
+ require_relative 'pixel_format_enum'
241
+ include PixelFormatEnum
242
+
243
+ def rle=(bool)
244
+ err = ::SDL.SetSurfaceRLE(self, bool ? 1 : 0)
245
+ raise RbSDL2Error if err < 0
246
+ end
247
+
248
+ def rle? = ::SDL.HasSurfaceRLE(self) == ::SDL::TRUE
249
+
250
+ # 画像をファイルへ書き込みます。
251
+ # obj には ファイルへのパス(文字列)、オブジェクト、RWOps オブジェクトを与えることができます。
252
+ # 例: File.open("path.bmp", "wb") { |f| Surface.save(f) }
253
+ # パスを与えた場合、書き込み後にクローズします。
254
+ # オブジェクトやRWOps オブジェクトを与えた場合、それらをクローズしません。
255
+ # SDL は書き込み時に前方向へのシークを行います。(開始点より前には行かない)
256
+ # ストリーム IO では使用できないでしょう。
257
+ # 読み込みができない場合は例外(RbSDL2::RbSDL2Error)を発生させます。
258
+ def save(obj)
259
+ RbSDL2.open_rw(obj) do |rw|
260
+ raise RbSDL2Error if ::SDL.SaveBMP_RW(self, rw, 0) < 0
261
+ end
262
+ nil
263
+ end
264
+
265
+ def size = [width, height]
266
+
267
+ def synchronize
268
+ ::SDL.LockSurface(self)
269
+ yield(self)
270
+ ensure
271
+ ::SDL.UnlockSurface(self)
272
+ end
273
+
274
+ def to_ptr = @st.to_ptr
275
+
276
+ def width = @st[:w]
277
+
278
+ alias w width
279
+ end
280
+ end
@@ -1,15 +1,21 @@
1
- module RbSDL2
2
- module TextInput
3
- class << self
4
- def active? = ::SDL2.SDL_IsTextInputActive == ::SDL2::SDL_TRUE
5
-
6
- def bounds=(rect)
7
- ::SDL2.SDL_SetTextInputRect(Rect.new(*rect))
8
- end
9
-
10
- def start = ::SDL2.SDL_StartTextInput
11
-
12
- def stop = ::SDL2.SDL_StopTextInput
13
- end
14
- end
15
- end
1
+ module RbSDL2
2
+ module TextInput
3
+ class << self
4
+ def active? = ::SDL.IsTextInputActive == ::SDL::TRUE
5
+
6
+ def bounds=(rect)
7
+ ::SDL.SetTextInputRect(Rect.new(*rect))
8
+ end
9
+
10
+ def clear_composition = ::SDL.ClearComposition
11
+
12
+ def screen_keyboard_support? = ::SDL.HasScreenKeyboardSupport == ::SDL::TRUE
13
+
14
+ def shown? = ::SDL.IsTextInputShown == ::SDL::TRUE
15
+
16
+ def start = ::SDL.StartTextInput
17
+
18
+ def stop = ::SDL.StopTextInput
19
+ end
20
+ end
21
+ end