sfml3-rb 0.2.2 → 0.3.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 (137) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +9 -0
  3. data/CHANGELOG.md +43 -17
  4. data/README.md +97 -29
  5. data/ext/audio/audio_enums.c +58 -20
  6. data/ext/audio/listener.c +89 -6
  7. data/ext/audio/music.c +206 -5
  8. data/ext/audio/sound.c +175 -5
  9. data/ext/audio/sound_buffer.c +189 -47
  10. data/ext/audio/sound_buffer_recorder.c +83 -16
  11. data/ext/audio/sound_recorder.c +172 -52
  12. data/ext/audio/sound_source_cone.c +108 -29
  13. data/ext/audio/sound_stream.c +178 -5
  14. data/ext/core/exceptions.c +10 -8
  15. data/ext/core/unicode.c +12 -2
  16. data/ext/ext.c +4 -0
  17. data/ext/graphics/blend_mode.c +203 -53
  18. data/ext/graphics/circle.c +271 -4
  19. data/ext/graphics/color.c +240 -90
  20. data/ext/graphics/drawable.c +15 -4
  21. data/ext/graphics/font.c +138 -25
  22. data/ext/graphics/glyph.c +31 -8
  23. data/ext/graphics/image.c +180 -37
  24. data/ext/graphics/polygon.c +293 -26
  25. data/ext/graphics/rect.c +211 -54
  26. data/ext/graphics/rectangle.c +279 -26
  27. data/ext/graphics/render_state.c +116 -2
  28. data/ext/graphics/render_texture.c +163 -2
  29. data/ext/graphics/shader.c +283 -17
  30. data/ext/graphics/shape.c +252 -26
  31. data/ext/graphics/sprite.c +216 -25
  32. data/ext/graphics/stencil_mode.c +148 -39
  33. data/ext/graphics/target.c +67 -22
  34. data/ext/graphics/target.h +15 -15
  35. data/ext/graphics/text.c +306 -6
  36. data/ext/graphics/texture.c +257 -3
  37. data/ext/graphics/transform.c +178 -5
  38. data/ext/graphics/transformable.c +126 -2
  39. data/ext/graphics/vertex.c +79 -2
  40. data/ext/graphics/vertex_array.c +128 -16
  41. data/ext/graphics/vertex_buffer.c +124 -2
  42. data/ext/graphics/view.c +130 -2
  43. data/ext/network/ftp.c +249 -10
  44. data/ext/network/http.c +156 -38
  45. data/ext/network/ip_address.c +107 -26
  46. data/ext/network/network_enums.c +248 -141
  47. data/ext/network/packet.c +273 -39
  48. data/ext/network/socket_selector.c +91 -19
  49. data/ext/network/tcp_listener.c +75 -16
  50. data/ext/network/tcp_socket.c +128 -25
  51. data/ext/network/udp_socket.c +122 -26
  52. data/ext/ports.rb +7 -0
  53. data/ext/system/buffer.c +41 -12
  54. data/ext/system/clock.c +68 -9
  55. data/ext/system/input_stream.c +94 -42
  56. data/ext/system/sleep.c +10 -2
  57. data/ext/system/time.c +172 -34
  58. data/ext/system/vec2.c +156 -35
  59. data/ext/system/vec3.c +166 -35
  60. data/ext/window/clipboard.c +47 -17
  61. data/ext/window/context.c +59 -9
  62. data/ext/window/context_settings.c +116 -38
  63. data/ext/window/cursor.c +39 -9
  64. data/ext/window/event.c +163 -42
  65. data/ext/window/joystick.c +69 -3
  66. data/ext/window/keyboard.c +168 -116
  67. data/ext/window/mouse.c +36 -2
  68. data/ext/window/sensor.c +28 -2
  69. data/ext/window/touch.c +20 -2
  70. data/ext/window/video_mode.c +90 -19
  71. data/ext/window/vulkan.c +34 -6
  72. data/ext/window/window.c +340 -16
  73. data/lib/sfml/version.rb +1 -1
  74. data/sig/audio/audio_enums.rbs +30 -0
  75. data/sig/audio/listener.rbs +16 -0
  76. data/sig/audio/music.rbs +56 -0
  77. data/sig/audio/sound.rbs +51 -0
  78. data/sig/audio/sound_buffer.rbs +17 -0
  79. data/sig/audio/sound_buffer_recorder.rbs +14 -0
  80. data/sig/audio/sound_recorder.rbs +17 -0
  81. data/sig/audio/sound_source_cone.rbs +14 -0
  82. data/sig/audio/sound_stream.rbs +51 -0
  83. data/sig/graphics/blend_mode.rbs +29 -0
  84. data/sig/graphics/circle.rbs +44 -0
  85. data/sig/graphics/color.rbs +39 -0
  86. data/sig/graphics/drawable.rbs +5 -0
  87. data/sig/graphics/font.rbs +20 -0
  88. data/sig/graphics/glyph.rbs +7 -0
  89. data/sig/graphics/image.rbs +22 -0
  90. data/sig/graphics/polygon.rbs +42 -0
  91. data/sig/graphics/rect.rbs +33 -0
  92. data/sig/graphics/rectangle.rbs +42 -0
  93. data/sig/graphics/render_state.rbs +21 -0
  94. data/sig/graphics/render_texture.rbs +37 -0
  95. data/sig/graphics/shader.rbs +39 -0
  96. data/sig/graphics/shape.rbs +38 -0
  97. data/sig/graphics/sprite.rbs +34 -0
  98. data/sig/graphics/stencil_mode.rbs +18 -0
  99. data/sig/graphics/target.rbs +10 -0
  100. data/sig/graphics/text.rbs +48 -0
  101. data/sig/graphics/texture.rbs +34 -0
  102. data/sig/graphics/transform.rbs +37 -0
  103. data/sig/graphics/transformable.rbs +25 -0
  104. data/sig/graphics/vertex.rbs +17 -0
  105. data/sig/graphics/vertex_array.rbs +17 -0
  106. data/sig/graphics/vertex_buffer.rbs +22 -0
  107. data/sig/graphics/view.rbs +24 -0
  108. data/sig/network/ftp.rbs +46 -0
  109. data/sig/network/http.rbs +27 -0
  110. data/sig/network/ip_address.rbs +22 -0
  111. data/sig/network/network_enums.rbs +95 -0
  112. data/sig/network/packet.rbs +40 -0
  113. data/sig/network/socket_selector.rbs +14 -0
  114. data/sig/network/tcp_listener.rbs +13 -0
  115. data/sig/network/tcp_socket.rbs +18 -0
  116. data/sig/network/udp_socket.rbs +17 -0
  117. data/sig/system/buffer.rbs +11 -0
  118. data/sig/system/clock.rbs +13 -0
  119. data/sig/system/input_stream.rbs +7 -0
  120. data/sig/system/sleep.rbs +3 -0
  121. data/sig/system/time.rbs +28 -0
  122. data/sig/system/vec2.rbs +26 -0
  123. data/sig/system/vec3.rbs +27 -0
  124. data/sig/window/clipboard.rbs +8 -0
  125. data/sig/window/context.rbs +11 -0
  126. data/sig/window/context_settings.rbs +20 -0
  127. data/sig/window/cursor.rbs +6 -0
  128. data/sig/window/event.rbs +20 -0
  129. data/sig/window/joystick.rbs +15 -0
  130. data/sig/window/keyboard.rbs +10 -0
  131. data/sig/window/mouse.rbs +9 -0
  132. data/sig/window/sensor.rbs +8 -0
  133. data/sig/window/touch.rbs +6 -0
  134. data/sig/window/video_mode.rbs +16 -0
  135. data/sig/window/vulkan.rbs +7 -0
  136. data/sig/window/window.rbs +57 -0
  137. metadata +66 -2
@@ -13,25 +13,28 @@ typedef struct {
13
13
 
14
14
  static VALUE rb_cContextSettings;
15
15
 
16
- static void ContextSettings_free(void *ptr) {
16
+ static void ContextSettings_free(void* ptr) {
17
17
  free(ptr);
18
18
  }
19
19
 
20
20
  static const rb_data_type_t ContextSettings_data_type = {
21
21
  .wrap_struct_name = "SFML::ContextSettings",
22
22
  .function = {.dmark = NULL, .dfree = ContextSettings_free, .dsize = NULL},
23
- .flags = RUBY_TYPED_FREE_IMMEDIATELY
24
- };
23
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY};
25
24
 
26
25
  static VALUE ContextSettings_wrap(sfContextSettings settings) {
27
- ContextSettings *ptr = malloc(sizeof(ContextSettings));
26
+ ContextSettings* ptr = malloc(sizeof(ContextSettings));
27
+
28
+ if (ptr == NULL) {
29
+ rb_raise(rb_eNoMemError, "failed to allocate context settings");
30
+ }
28
31
 
29
32
  ptr->settings = settings;
30
33
 
31
34
  return TypedData_Wrap_Struct(rb_cContextSettings, &ContextSettings_data_type, ptr);
32
35
  }
33
36
 
34
- static const char *context_flag_name(VALUE value) {
37
+ static const char* context_flag_name(VALUE value) {
35
38
  if (SYMBOL_P(value)) {
36
39
  return rb_id2name(SYM2ID(value));
37
40
  }
@@ -39,38 +42,46 @@ static const char *context_flag_name(VALUE value) {
39
42
  return StringValueCStr(value);
40
43
  }
41
44
 
42
- static VALUE ContextSettings_new(int argc, VALUE *argv, VALUE klass) { sfContextSettings settings = {0, 0, 0, 1, 1, sfContextDefault, false};
45
+ /* call-seq:
46
+ * ContextSettings.new(depth_bits = 0, stencil_bits = 0, antialiasing_level = 0, major_version =
47
+ * 1, minor_version = 1, flags = :default, srgb_capable = false) -> ContextSettings
48
+ *
49
+ * @return [ContextSettings]
50
+ * @raise [ArgumentError] if +flags+ contains an unknown attribute name
51
+ */
52
+ static VALUE ContextSettings_new(int argc, VALUE* argv, VALUE klass) {
53
+ sfContextSettings settings = {0, 0, 0, 1, 1, sfContextDefault, false};
43
54
  VALUE rb_depth, rb_stencil, rb_antialiasing, rb_major, rb_minor, rb_flags, rb_srgb;
44
55
  VALUE self;
45
56
 
46
- rb_scan_args(argc, argv, "07", &rb_depth, &rb_stencil, &rb_antialiasing, &rb_major, &rb_minor, &rb_flags,
47
- &rb_srgb);
57
+ rb_scan_args(argc, argv, "07", &rb_depth, &rb_stencil, &rb_antialiasing, &rb_major, &rb_minor,
58
+ &rb_flags, &rb_srgb);
48
59
 
49
60
  if (!NIL_P(rb_depth)) {
50
- settings.depthBits = (unsigned int) NUM2UINT(rb_depth);
61
+ settings.depthBits = (unsigned int)NUM2UINT(rb_depth);
51
62
  }
52
63
 
53
64
  if (!NIL_P(rb_stencil)) {
54
- settings.stencilBits = (unsigned int) NUM2UINT(rb_stencil);
65
+ settings.stencilBits = (unsigned int)NUM2UINT(rb_stencil);
55
66
  }
56
67
 
57
68
  if (!NIL_P(rb_antialiasing)) {
58
- settings.antiAliasingLevel = (unsigned int) NUM2UINT(rb_antialiasing);
69
+ settings.antiAliasingLevel = (unsigned int)NUM2UINT(rb_antialiasing);
59
70
  }
60
71
 
61
72
  if (!NIL_P(rb_major)) {
62
- settings.majorVersion = (unsigned int) NUM2UINT(rb_major);
73
+ settings.majorVersion = (unsigned int)NUM2UINT(rb_major);
63
74
  }
64
75
 
65
76
  if (!NIL_P(rb_minor)) {
66
- settings.minorVersion = (unsigned int) NUM2UINT(rb_minor);
77
+ settings.minorVersion = (unsigned int)NUM2UINT(rb_minor);
67
78
  }
68
79
 
69
80
  if (!NIL_P(rb_flags)) {
70
81
  uint32_t flags = 0;
71
82
 
72
83
  if (RB_INTEGER_TYPE_P(rb_flags)) {
73
- flags = (uint32_t) NUM2UINT(rb_flags);
84
+ flags = (uint32_t)NUM2UINT(rb_flags);
74
85
  } else if (SYMBOL_P(rb_flags) || RB_TYPE_P(rb_flags, T_STRING)) {
75
86
  rb_flags = rb_ary_new_from_args(1, rb_flags);
76
87
  }
@@ -78,7 +89,7 @@ static VALUE ContextSettings_new(int argc, VALUE *argv, VALUE klass) { sfCont
78
89
  if (RB_TYPE_P(rb_flags, T_ARRAY)) {
79
90
  for (long i = 0; i < RARRAY_LEN(rb_flags); i++) {
80
91
  VALUE entry = rb_ary_entry(rb_flags, i);
81
- const char *name = context_flag_name(entry);
92
+ const char* name = context_flag_name(entry);
82
93
 
83
94
  if (strcmp(name, "core") == 0) {
84
95
  flags |= sfContextCore;
@@ -102,23 +113,37 @@ static VALUE ContextSettings_new(int argc, VALUE *argv, VALUE klass) { sfCont
102
113
  return self;
103
114
  }
104
115
 
105
- #define CONTEXT_SETTINGS_UINT_ACCESSOR(name, field) \
106
- static VALUE ContextSettings_get_##name(VALUE self) { \
107
- return UINT2NUM(((ContextSettings *) Get_ContextSettings_Struct(self))->settings.field); \
108
- } \
109
- static VALUE ContextSettings_set_##name(VALUE self, VALUE rb_value) { \
110
- ((ContextSettings *) Get_ContextSettings_Struct(self))->settings.field = (unsigned int) NUM2UINT(rb_value); \
111
- return rb_value; \
116
+ #define CONTEXT_SETTINGS_UINT_ACCESSOR(name, field) \
117
+ static VALUE ContextSettings_get_##name(VALUE self) { \
118
+ return UINT2NUM(((ContextSettings*)Get_ContextSettings_Struct(self))->settings.field); \
119
+ } \
120
+ static VALUE ContextSettings_set_##name(VALUE self, VALUE rb_value) { \
121
+ rb_check_frozen(self); \
122
+ ((ContextSettings*)Get_ContextSettings_Struct(self))->settings.field = \
123
+ (unsigned int)NUM2UINT(rb_value); \
124
+ return rb_value; \
112
125
  }
113
126
 
127
+ /* Macro-generated accessor pairs (depth_bits, stencil_bits,
128
+ * antialiasing_level, major_version, minor_version); documented together via
129
+ * Document-class's @!attribute tags below since the comment can't attach to
130
+ * an individual macro expansion. */
114
131
  CONTEXT_SETTINGS_UINT_ACCESSOR(depth_bits, depthBits)
115
132
  CONTEXT_SETTINGS_UINT_ACCESSOR(stencil_bits, stencilBits)
116
133
  CONTEXT_SETTINGS_UINT_ACCESSOR(antialiasing_level, antiAliasingLevel)
117
134
  CONTEXT_SETTINGS_UINT_ACCESSOR(major_version, majorVersion)
118
135
  CONTEXT_SETTINGS_UINT_ACCESSOR(minor_version, minorVersion)
119
136
 
137
+ /* Document-method: SFML::ContextSettings#attribute_flags
138
+ * call-seq: attribute_flags -> Array<Symbol>
139
+ *
140
+ * Returns the context attribute flags as a list of symbols.
141
+ *
142
+ * @return [Array<Symbol>] a subset of +[:core, :debug]+, or +[:default]+ if
143
+ * neither is set
144
+ */
120
145
  static VALUE ContextSettings_get_attribute_flags(VALUE self) {
121
- uint32_t flags = ((ContextSettings *) Get_ContextSettings_Struct(self))->settings.attributeFlags;
146
+ uint32_t flags = ((ContextSettings*)Get_ContextSettings_Struct(self))->settings.attributeFlags;
122
147
  VALUE array = rb_ary_new();
123
148
 
124
149
  if ((flags & sfContextCore) != 0) {
@@ -136,18 +161,28 @@ static VALUE ContextSettings_get_attribute_flags(VALUE self) {
136
161
  return array;
137
162
  }
138
163
 
164
+ /* Document-method: SFML::ContextSettings#attribute_flags=
165
+ * call-seq: attribute_flags = value -> value
166
+ *
167
+ * Sets the context attribute flags from +value+, an Integer bitmask or a
168
+ * Symbol/Array of +:core+ and +:debug+.
169
+ *
170
+ * @return [Integer, Array<Symbol>] +value+
171
+ */
139
172
  static VALUE ContextSettings_set_attribute_flags(VALUE self, VALUE rb_value) {
140
- ContextSettings *settings = Get_ContextSettings_Struct(self);
173
+ ContextSettings* settings = Get_ContextSettings_Struct(self);
141
174
  uint32_t flags = 0;
142
175
 
176
+ rb_check_frozen(self);
177
+
143
178
  if (RB_INTEGER_TYPE_P(rb_value)) {
144
- flags = (uint32_t) NUM2UINT(rb_value);
179
+ flags = (uint32_t)NUM2UINT(rb_value);
145
180
  } else {
146
181
  VALUE array = RB_TYPE_P(rb_value, T_ARRAY) ? rb_value : rb_ary_new_from_args(1, rb_value);
147
182
 
148
183
  for (long i = 0; i < RARRAY_LEN(array); i++) {
149
184
  VALUE entry = rb_ary_entry(array, i);
150
- const char *name = context_flag_name(entry);
185
+ const char* name = context_flag_name(entry);
151
186
 
152
187
  if (strcmp(name, "core") == 0) {
153
188
  flags |= sfContextCore;
@@ -162,34 +197,77 @@ static VALUE ContextSettings_set_attribute_flags(VALUE self, VALUE rb_value) {
162
197
  return rb_value;
163
198
  }
164
199
 
200
+ /* call-seq: srgb_capable? -> true or false
201
+ *
202
+ * Returns +true+ if the context was created with sRGB-capable framebuffers.
203
+ *
204
+ * @return [Boolean]
205
+ */
165
206
  static VALUE ContextSettings_get_srgb(VALUE self) {
166
- return BOOL2RB(((ContextSettings *) Get_ContextSettings_Struct(self))->settings.sRgbCapable);
207
+ return BOOL2RB(((ContextSettings*)Get_ContextSettings_Struct(self))->settings.sRgbCapable);
167
208
  }
168
209
 
210
+ /* call-seq:
211
+ * srgb_capable=(value) -> true or false
212
+ *
213
+ * Requests sRGB-capable framebuffers when +value+ is +true+.
214
+ *
215
+ * @return [Boolean] +value+
216
+ */
169
217
  static VALUE ContextSettings_set_srgb(VALUE self, VALUE rb_value) {
170
- ((ContextSettings *) Get_ContextSettings_Struct(self))->settings.sRgbCapable = RTEST(rb_value);
218
+ rb_check_frozen(self);
219
+ ((ContextSettings*)Get_ContextSettings_Struct(self))->settings.sRgbCapable = RTEST(rb_value);
171
220
  return rb_value;
172
221
  }
173
222
 
174
- void Init_ContextSettings(VALUE rb_module) {
175
- rb_cContextSettings = rb_define_class_under(rb_module, "ContextSettings", rb_cObject);
223
+ /* Document-class: SFML::ContextSettings
224
+ * Settings requested when creating a Window or Context: depth/stencil buffer
225
+ * sizes, antialiasing level, requested OpenGL version, and attribute flags.
226
+ *
227
+ * The +depth_bits+/+stencil_bits+/+antialiasing_level+/+major_version+/
228
+ * +minor_version+ accessors are generated through a shared C macro, so
229
+ * (unlike this class's other accessors) they are documented here rather than
230
+ * above their own definitions.
231
+ *
232
+ * @!attribute depth_bits
233
+ * Number of bits per pixel requested for the depth buffer.
234
+ * @return [Integer] requested depth buffer bits per pixel
235
+ * @!attribute stencil_bits
236
+ * Number of bits per pixel requested for the stencil buffer.
237
+ * @return [Integer] requested stencil buffer bits per pixel
238
+ * @!attribute antialiasing_level
239
+ * Requested antialiasing level.
240
+ * @return [Integer] requested antialiasing level
241
+ * @!attribute major_version
242
+ * Requested OpenGL major version.
243
+ * @return [Integer] requested OpenGL major version
244
+ * @!attribute minor_version
245
+ * Requested OpenGL minor version.
246
+ * @return [Integer] requested OpenGL minor version
247
+ */
248
+ void Init_ContextSettings(VALUE rb_mSFML) {
249
+ rb_cContextSettings = rb_define_class_under(rb_mSFML, "ContextSettings", rb_cObject);
176
250
 
177
251
  rb_define_singleton_method(rb_cContextSettings, "new", ContextSettings_new, -1);
178
252
 
179
253
  rb_define_method(rb_cContextSettings, "depth_bits", ContextSettings_get_depth_bits, 0);
180
254
  rb_define_method(rb_cContextSettings, "stencil_bits", ContextSettings_get_stencil_bits, 0);
181
- rb_define_method(rb_cContextSettings, "antialiasing_level", ContextSettings_get_antialiasing_level, 0);
255
+ rb_define_method(rb_cContextSettings, "antialiasing_level",
256
+ ContextSettings_get_antialiasing_level, 0);
182
257
  rb_define_method(rb_cContextSettings, "major_version", ContextSettings_get_major_version, 0);
183
258
  rb_define_method(rb_cContextSettings, "minor_version", ContextSettings_get_minor_version, 0);
184
- rb_define_method(rb_cContextSettings, "attribute_flags", ContextSettings_get_attribute_flags, 0);
259
+ rb_define_method(rb_cContextSettings, "attribute_flags", ContextSettings_get_attribute_flags,
260
+ 0);
185
261
  rb_define_method(rb_cContextSettings, "srgb_capable?", ContextSettings_get_srgb, 0);
186
262
 
187
263
  rb_define_method(rb_cContextSettings, "depth_bits=", ContextSettings_set_depth_bits, 1);
188
264
  rb_define_method(rb_cContextSettings, "stencil_bits=", ContextSettings_set_stencil_bits, 1);
189
- rb_define_method(rb_cContextSettings, "antialiasing_level=", ContextSettings_set_antialiasing_level, 1);
265
+ rb_define_method(rb_cContextSettings,
266
+ "antialiasing_level=", ContextSettings_set_antialiasing_level, 1);
190
267
  rb_define_method(rb_cContextSettings, "major_version=", ContextSettings_set_major_version, 1);
191
268
  rb_define_method(rb_cContextSettings, "minor_version=", ContextSettings_set_minor_version, 1);
192
- rb_define_method(rb_cContextSettings, "attribute_flags=", ContextSettings_set_attribute_flags, 1);
269
+ rb_define_method(rb_cContextSettings, "attribute_flags=", ContextSettings_set_attribute_flags,
270
+ 1);
193
271
  rb_define_method(rb_cContextSettings, "srgb_capable=", ContextSettings_set_srgb, 1);
194
272
  }
195
273
 
@@ -197,22 +275,22 @@ VALUE Get_Klass_ContextSettings(void) {
197
275
  return rb_cContextSettings;
198
276
  }
199
277
 
200
- void *Get_ContextSettings_Struct(VALUE self) {
201
- ContextSettings *ptr;
278
+ void* Get_ContextSettings_Struct(VALUE self) {
279
+ ContextSettings* ptr;
202
280
  TypedData_Get_Struct(self, ContextSettings, &ContextSettings_data_type, ptr);
203
281
  return ptr;
204
282
  }
205
283
 
206
284
  sfContextSettings context_settings_from_rb(VALUE rb_settings) {
207
285
  if (NIL_P(rb_settings)) {
208
- return (sfContextSettings) {0, 0, 0, 1, 1, sfContextDefault, false};
286
+ return (sfContextSettings){0, 0, 0, 1, 1, sfContextDefault, false};
209
287
  }
210
288
 
211
289
  if (!rb_obj_is_kind_of(rb_settings, rb_cContextSettings)) {
212
290
  raise_invalid_argument_class(rb_cContextSettings);
213
291
  }
214
292
 
215
- return ((ContextSettings *) Get_ContextSettings_Struct(rb_settings))->settings;
293
+ return ((ContextSettings*)Get_ContextSettings_Struct(rb_settings))->settings;
216
294
  }
217
295
 
218
296
  VALUE context_settings_to_rb(sfContextSettings settings) {
data/ext/window/cursor.c CHANGED
@@ -9,17 +9,16 @@
9
9
 
10
10
  static VALUE rb_cCursor;
11
11
 
12
- static void Cursor_free(void *ptr) {
12
+ static void Cursor_free(void* ptr) {
13
13
  sfCursor_destroy(ptr);
14
14
  }
15
15
 
16
16
  static const rb_data_type_t Cursor_data_type = {
17
17
  .wrap_struct_name = "SFML::Cursor",
18
18
  .function = {.dmark = NULL, .dfree = Cursor_free, .dsize = NULL},
19
- .flags = RUBY_TYPED_FREE_IMMEDIATELY
20
- };
19
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY};
21
20
 
22
- static VALUE Cursor_wrap(sfCursor *cursor) {
21
+ static VALUE Cursor_wrap(sfCursor* cursor) {
23
22
  if (cursor == NULL) {
24
23
  rb_raise(rb_eRuntimeError, "failed to create cursor");
25
24
  }
@@ -27,19 +26,50 @@ static VALUE Cursor_wrap(sfCursor *cursor) {
27
26
  return TypedData_Wrap_Struct(rb_cCursor, &Cursor_data_type, cursor);
28
27
  }
29
28
 
29
+ /* call-seq:
30
+ * Cursor.from_pixels(pixels, size, hotspot) -> Cursor
31
+ *
32
+ * Creates a cursor from RGBA32 pixel data (+width * height * 4+ bytes,
33
+ * row-major, top-to-bottom).
34
+ *
35
+ * @return [Cursor]
36
+ * @raise [ArgumentError] if +pixels+ is shorter than required
37
+ * @raise [RuntimeError] if cursor creation fails
38
+ */
30
39
  static VALUE Cursor_from_pixels(VALUE klass, VALUE rb_pixels, VALUE rb_size, VALUE rb_hotspot) {
40
+ sfVector2u size = vec2u_from_rb(rb_size);
41
+ size_t expected = (size_t)size.x * size.y * 4;
42
+
31
43
  StringValue(rb_pixels);
32
44
 
33
- return Cursor_wrap(sfCursor_createFromPixels((const uint8_t *) RSTRING_PTR(rb_pixels), vec2u_from_rb(rb_size),
45
+ if ((size_t)RSTRING_LEN(rb_pixels) < expected) {
46
+ rb_raise(rb_eArgError, "pixel data too short: expected %zu bytes", expected);
47
+ }
48
+
49
+ return Cursor_wrap(sfCursor_createFromPixels((const uint8_t*)RSTRING_PTR(rb_pixels), size,
34
50
  vec2u_from_rb(rb_hotspot)));
35
51
  }
36
52
 
53
+ /* call-seq:
54
+ * Cursor.from_system(type) -> Cursor
55
+ *
56
+ * Creates a cursor from a native system cursor type (a Symbol, e.g.
57
+ * +:arrow+, +:hand+, +:crosshair+; see the cursor type symbols this binding
58
+ * accepts).
59
+ *
60
+ * @return [Cursor]
61
+ * @raise [RuntimeError] if cursor creation fails
62
+ */
37
63
  static VALUE Cursor_from_system(VALUE klass, VALUE rb_type) {
38
64
  return Cursor_wrap(sfCursor_createFromSystem(cursor_type_from_rb(rb_type)));
39
65
  }
40
66
 
41
- void Init_Cursor(VALUE rb_module) {
42
- rb_cCursor = rb_define_class_under(rb_module, "Cursor", rb_cObject);
67
+ /* Document-class: SFML::Cursor
68
+ * A native mouse cursor, either built from raw pixel data or one of the
69
+ * platform's built-in system cursors. Assign to Window#cursor= to apply.
70
+ */
71
+ void Init_Cursor(VALUE rb_mSFML) {
72
+ rb_cCursor = rb_define_class_under(rb_mSFML, "Cursor", rb_cObject);
43
73
 
44
74
  rb_define_singleton_method(rb_cCursor, "from_pixels", Cursor_from_pixels, 3);
45
75
  rb_define_singleton_method(rb_cCursor, "from_system", Cursor_from_system, 1);
@@ -49,8 +79,8 @@ VALUE Get_Klass_Cursor(void) {
49
79
  return rb_cCursor;
50
80
  }
51
81
 
52
- const sfCursor *Get_Cursor_Struct(VALUE self) {
53
- sfCursor *ptr;
82
+ const sfCursor* Get_Cursor_Struct(VALUE self) {
83
+ sfCursor* ptr;
54
84
  TypedData_Get_Struct(self, sfCursor, &Cursor_data_type, ptr);
55
85
  return ptr;
56
86
  }