bitmap-plus-plus 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 +7 -0
- data/CHANGELOG.md +40 -0
- data/LICENSE +25 -0
- data/README.md +75 -0
- data/examples/colormaps.rb +1857 -0
- data/examples/draw_primitives.rb +53 -0
- data/examples/julia.rb +68 -0
- data/examples/mandelbrot.rb +68 -0
- data/examples/random_colors.rb +37 -0
- data/examples/transformations.rb +84 -0
- data/ext/BitmapPlusPlus-rb.cpp +420 -0
- data/ext/BitmapPlusPlus-rb.hpp +11 -0
- data/ext/BitmapPlusPlus.hpp +659 -0
- data/ext/CMakeLists.txt +170 -0
- data/ext/CMakePresets.json +209 -0
- data/lib/bitmap-plus-plus/version.rb +3 -0
- data/lib/bitmap-plus-plus.rb +3 -0
- data/sig/Bmp/Bitmap.rbs +39 -0
- data/sig/Bmp/BitmapHeader.rbs +22 -0
- data/sig/Bmp/Exception.rbs +5 -0
- data/sig/Bmp/Pixel.rbs +16 -0
- data/sig/Rice/Arg.rbs +6 -0
- data/sig/Rice/Buffer/342/211/272Rice/352/236/211/352/236/211detail/352/236/211/352/236/211ParameterAbstract/342/210/227/342/211/273.rbs +15 -0
- data/sig/Rice/Buffer/342/211/272char/342/211/273.rbs +16 -0
- data/sig/Rice/ModuleRegistry.rbs +5 -0
- data/sig/Rice/Native.rbs +9 -0
- data/sig/Rice/NativeKind.rbs +20 -0
- data/sig/Rice/NativeRegistry.rbs +5 -0
- data/sig/Rice/Parameter.rbs +7 -0
- data/sig/Rice/Pointer/342/211/272Rice/352/236/211/352/236/211detail/352/236/211/352/236/211ParameterAbstract/342/210/227/342/211/273.rbs +5 -0
- data/sig/Rice/Pointer/342/211/272char/342/211/273.rbs +5 -0
- data/sig/Rice/Reference/342/211/272char/342/211/273.rbs +6 -0
- data/sig/Rice/Reference/342/211/272int/342/211/273.rbs +6 -0
- data/sig/Rice/Reference/342/211/272unsigned/302/240Int64/342/211/273.rbs +6 -0
- data/sig/Rice/Registries.rbs +8 -0
- data/sig/Rice/TypeRegistry.rbs +5 -0
- data/sig/Std/Exception.rbs +6 -0
- data/sig/Std/Filesystem/Path.rbs +6 -0
- data/sig/Std/RuntimeError.rbs +6 -0
- data/sig/Std/Vector/342/211/272Rice/352/236/211/352/236/211detail/352/236/211/352/236/211ParameterAbstract/302/240const/342/210/227/342/211/273.rbs +33 -0
- metadata +116 -0
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BitmapPlusPlus Ruby Bindings
|
|
3
|
+
*
|
|
4
|
+
* This file demonstrates how to use Rice to create Ruby bindings for a C++ library.
|
|
5
|
+
* Rice is a C++ header-only library that makes it easy to create Ruby extensions.
|
|
6
|
+
*
|
|
7
|
+
* Key Rice concepts demonstrated:
|
|
8
|
+
*
|
|
9
|
+
* 1. MODULES: Use define_module() to create Ruby modules that namespace your classes
|
|
10
|
+
*
|
|
11
|
+
* 2. CLASSES: Use define_class_under<CppClass>(module, "RubyName") to wrap C++ classes
|
|
12
|
+
* - The template parameter is the C++ class being wrapped
|
|
13
|
+
* - The first argument is the parent module
|
|
14
|
+
* - The second argument is the Ruby class name
|
|
15
|
+
*
|
|
16
|
+
* 3. INHERITANCE: Use define_class_under<Derived, Base>() for class hierarchies
|
|
17
|
+
*
|
|
18
|
+
* 4. CONSTRUCTORS: Use define_constructor(Constructor<Class, Args...>())
|
|
19
|
+
* - Multiple constructors can be defined for overloading
|
|
20
|
+
* - Use Arg("name") to provide named parameters for better error messages
|
|
21
|
+
* - Use Arg("name") = default_value for default arguments
|
|
22
|
+
*
|
|
23
|
+
* 5. METHODS: Use define_method("ruby_name", &Class::method)
|
|
24
|
+
* - Methods are automatically wrapped with type conversion
|
|
25
|
+
* - Use Arg("name") for named parameters
|
|
26
|
+
*
|
|
27
|
+
* 6. OVERLOADED METHODS: Use template syntax to disambiguate overloads
|
|
28
|
+
* - define_method<ReturnType(Class::*)(Args...)>("name", &Class::method)
|
|
29
|
+
*
|
|
30
|
+
* 7. ATTRIBUTES: Use define_attr("name", &Class::member) for struct members
|
|
31
|
+
* - Creates both getter and setter methods
|
|
32
|
+
*
|
|
33
|
+
* 8. OPERATORS: Map C++ operators to Ruby methods
|
|
34
|
+
* - "==" for operator==, "!=" for operator!=, "[]" for operator[], etc.
|
|
35
|
+
*
|
|
36
|
+
* 9. LAMBDAS: Use lambdas for custom behavior not directly mappable
|
|
37
|
+
* - Useful for []= operator which doesn't exist in C++
|
|
38
|
+
*
|
|
39
|
+
* 10. CONSTANTS: Use module.define_constant("NAME", value)
|
|
40
|
+
*
|
|
41
|
+
* 11. ITERATORS: Use define_iterator() to make C++ iterators work with Ruby's each
|
|
42
|
+
*
|
|
43
|
+
* 12. EXCEPTION HANDLING: Rice automatically converts C++ exceptions to Ruby exceptions
|
|
44
|
+
* - Use Rice::detail::cpp_protect() to wrap initialization code
|
|
45
|
+
*
|
|
46
|
+
* 13. STL SUPPORT: Include <rice/stl.hpp> for automatic std::string, std::vector, etc. conversion
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
#include "BitmapPlusPlus.hpp"
|
|
50
|
+
#include "BitmapPlusPlus-rb.hpp"
|
|
51
|
+
|
|
52
|
+
using namespace Rice;
|
|
53
|
+
|
|
54
|
+
// Global class references (optional, but useful for cross-referencing)
|
|
55
|
+
Rice::Class rb_cBmpBitmap;
|
|
56
|
+
Rice::Class rb_cBmpBitmapHeader;
|
|
57
|
+
Rice::Class rb_cBmpException;
|
|
58
|
+
Rice::Class rb_cBmpPixel;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Main initialization function
|
|
62
|
+
*
|
|
63
|
+
* This function defines all the Ruby bindings. It's called from Init_bitmap_plus_plus()
|
|
64
|
+
* which is the entry point that Ruby calls when the extension is loaded.
|
|
65
|
+
*/
|
|
66
|
+
void initialize()
|
|
67
|
+
{
|
|
68
|
+
// ============================================================================
|
|
69
|
+
// MODULE DEFINITION
|
|
70
|
+
// ============================================================================
|
|
71
|
+
// Create a Ruby module to namespace all our classes.
|
|
72
|
+
// In Ruby, this creates: module Bmp; end
|
|
73
|
+
Module rb_mBmp = define_module("Bmp");
|
|
74
|
+
|
|
75
|
+
// ============================================================================
|
|
76
|
+
// CONSTANTS
|
|
77
|
+
// ============================================================================
|
|
78
|
+
// Define module-level constants. These become Bmp::BITMAP_BUFFER_MAGIC, etc.
|
|
79
|
+
rb_mBmp.define_constant("BITMAP_BUFFER_MAGIC", bmp::BITMAP_BUFFER_MAGIC);
|
|
80
|
+
|
|
81
|
+
// ============================================================================
|
|
82
|
+
// STRUCT BINDING: BitmapHeader
|
|
83
|
+
// ============================================================================
|
|
84
|
+
// Wrap a simple C++ struct. Use define_attr() to expose struct members.
|
|
85
|
+
// define_attr() creates both getter and setter methods automatically.
|
|
86
|
+
rb_cBmpBitmapHeader = define_class_under<bmp::BitmapHeader>(rb_mBmp, "BitmapHeader")
|
|
87
|
+
// Default constructor
|
|
88
|
+
.define_constructor(Constructor<bmp::BitmapHeader>())
|
|
89
|
+
// Expose all struct members as Ruby attributes
|
|
90
|
+
.define_attr("magic", &bmp::BitmapHeader::magic)
|
|
91
|
+
.define_attr("file_size", &bmp::BitmapHeader::file_size)
|
|
92
|
+
.define_attr("reserved1", &bmp::BitmapHeader::reserved1)
|
|
93
|
+
.define_attr("reserved2", &bmp::BitmapHeader::reserved2)
|
|
94
|
+
.define_attr("offset_bits", &bmp::BitmapHeader::offset_bits)
|
|
95
|
+
.define_attr("size", &bmp::BitmapHeader::size)
|
|
96
|
+
.define_attr("width", &bmp::BitmapHeader::width)
|
|
97
|
+
.define_attr("height", &bmp::BitmapHeader::height)
|
|
98
|
+
.define_attr("planes", &bmp::BitmapHeader::planes)
|
|
99
|
+
.define_attr("bits_per_pixel", &bmp::BitmapHeader::bits_per_pixel)
|
|
100
|
+
.define_attr("compression", &bmp::BitmapHeader::compression)
|
|
101
|
+
.define_attr("size_image", &bmp::BitmapHeader::size_image)
|
|
102
|
+
.define_attr("x_pixels_per_meter", &bmp::BitmapHeader::x_pixels_per_meter)
|
|
103
|
+
.define_attr("y_pixels_per_meter", &bmp::BitmapHeader::y_pixels_per_meter)
|
|
104
|
+
.define_attr("clr_used", &bmp::BitmapHeader::clr_used)
|
|
105
|
+
.define_attr("clr_important", &bmp::BitmapHeader::clr_important);
|
|
106
|
+
|
|
107
|
+
// ============================================================================
|
|
108
|
+
// STRUCT BINDING: Pixel
|
|
109
|
+
// ============================================================================
|
|
110
|
+
// A more complex struct with multiple constructors and operators
|
|
111
|
+
rb_cBmpPixel = define_class_under<bmp::Pixel>(rb_mBmp, "Pixel")
|
|
112
|
+
// Expose RGB components as attributes
|
|
113
|
+
.define_attr("r", &bmp::Pixel::r)
|
|
114
|
+
.define_attr("g", &bmp::Pixel::g)
|
|
115
|
+
.define_attr("b", &bmp::Pixel::b)
|
|
116
|
+
|
|
117
|
+
// MULTIPLE CONSTRUCTORS (overloading)
|
|
118
|
+
// Rice supports multiple constructors with different signatures
|
|
119
|
+
.define_constructor(Constructor<bmp::Pixel>()) // Default: black pixel
|
|
120
|
+
|
|
121
|
+
// Constructor with named argument for better error messages
|
|
122
|
+
// In Ruby: Pixel.new(rgb: 0xFF0000)
|
|
123
|
+
.define_constructor(Constructor<bmp::Pixel, const std::int32_t>(),
|
|
124
|
+
Arg("rgb"))
|
|
125
|
+
|
|
126
|
+
// Constructor with multiple named arguments
|
|
127
|
+
// In Ruby: Pixel.new(red: 255, green: 128, blue: 64)
|
|
128
|
+
.define_constructor(Constructor<bmp::Pixel, const std::uint8_t, const std::uint8_t, const std::uint8_t>(),
|
|
129
|
+
Arg("red"), Arg("green"), Arg("blue"))
|
|
130
|
+
|
|
131
|
+
// OPERATORS
|
|
132
|
+
// Map C++ operators to Ruby methods
|
|
133
|
+
.define_method("==", &bmp::Pixel::operator==,
|
|
134
|
+
Arg("other"))
|
|
135
|
+
.define_method("!=", &bmp::Pixel::operator!=,
|
|
136
|
+
Arg("other"))
|
|
137
|
+
|
|
138
|
+
// LAMBDA for custom functionality
|
|
139
|
+
// The assign method copies values from another pixel
|
|
140
|
+
.define_method("assign", [](bmp::Pixel& self, bmp::Pixel& other)
|
|
141
|
+
{
|
|
142
|
+
self.r = other.r;
|
|
143
|
+
self.g = other.g;
|
|
144
|
+
self.b = other.b;
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
// INSPECT METHOD for debugging in IRB
|
|
148
|
+
.define_method("inspect", [](const bmp::Pixel& self) -> std::string
|
|
149
|
+
{
|
|
150
|
+
return "#<Bmp::Pixel r=" + std::to_string(self.r) +
|
|
151
|
+
" g=" + std::to_string(self.g) +
|
|
152
|
+
" b=" + std::to_string(self.b) + ">";
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
.define_method("to_s", [](const bmp::Pixel& self) -> std::string
|
|
156
|
+
{
|
|
157
|
+
return "Pixel(" + std::to_string(self.r) + ", " +
|
|
158
|
+
std::to_string(self.g) + ", " +
|
|
159
|
+
std::to_string(self.b) + ")";
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// ============================================================================
|
|
163
|
+
// COLOR CONSTANTS
|
|
164
|
+
// ============================================================================
|
|
165
|
+
// Define predefined colors as module constants
|
|
166
|
+
// In Ruby: Bmp::Red, Bmp::Blue, etc.
|
|
167
|
+
rb_mBmp.define_constant("Aqua", bmp::Aqua);
|
|
168
|
+
rb_mBmp.define_constant("Beige", bmp::Beige);
|
|
169
|
+
rb_mBmp.define_constant("Black", bmp::Black);
|
|
170
|
+
rb_mBmp.define_constant("Blue", bmp::Blue);
|
|
171
|
+
rb_mBmp.define_constant("Brown", bmp::Brown);
|
|
172
|
+
rb_mBmp.define_constant("Chocolate", bmp::Chocolate);
|
|
173
|
+
rb_mBmp.define_constant("Coral", bmp::Coral);
|
|
174
|
+
rb_mBmp.define_constant("Crimson", bmp::Crimson);
|
|
175
|
+
rb_mBmp.define_constant("Cyan", bmp::Cyan);
|
|
176
|
+
rb_mBmp.define_constant("Firebrick", bmp::Firebrick);
|
|
177
|
+
rb_mBmp.define_constant("Gold", bmp::Gold);
|
|
178
|
+
rb_mBmp.define_constant("Gray", bmp::Gray);
|
|
179
|
+
rb_mBmp.define_constant("Green", bmp::Green);
|
|
180
|
+
rb_mBmp.define_constant("Indigo", bmp::Indigo);
|
|
181
|
+
rb_mBmp.define_constant("Lavender", bmp::Lavender);
|
|
182
|
+
rb_mBmp.define_constant("Lime", bmp::Lime);
|
|
183
|
+
rb_mBmp.define_constant("Magenta", bmp::Magenta);
|
|
184
|
+
rb_mBmp.define_constant("Maroon", bmp::Maroon);
|
|
185
|
+
rb_mBmp.define_constant("Navy", bmp::Navy);
|
|
186
|
+
rb_mBmp.define_constant("Olive", bmp::Olive);
|
|
187
|
+
rb_mBmp.define_constant("Orange", bmp::Orange);
|
|
188
|
+
rb_mBmp.define_constant("Pink", bmp::Pink);
|
|
189
|
+
rb_mBmp.define_constant("Purple", bmp::Purple);
|
|
190
|
+
rb_mBmp.define_constant("Red", bmp::Red);
|
|
191
|
+
rb_mBmp.define_constant("Salmon", bmp::Salmon);
|
|
192
|
+
rb_mBmp.define_constant("Silver", bmp::Silver);
|
|
193
|
+
rb_mBmp.define_constant("Snow", bmp::Snow);
|
|
194
|
+
rb_mBmp.define_constant("Teal", bmp::Teal);
|
|
195
|
+
rb_mBmp.define_constant("Tomato", bmp::Tomato);
|
|
196
|
+
rb_mBmp.define_constant("Turquoise", bmp::Turquoise);
|
|
197
|
+
rb_mBmp.define_constant("Violet", bmp::Violet);
|
|
198
|
+
rb_mBmp.define_constant("White", bmp::White);
|
|
199
|
+
rb_mBmp.define_constant("Wheat", bmp::Wheat);
|
|
200
|
+
rb_mBmp.define_constant("Yellow", bmp::Yellow);
|
|
201
|
+
|
|
202
|
+
// ============================================================================
|
|
203
|
+
// EXCEPTION CLASS with INHERITANCE
|
|
204
|
+
// ============================================================================
|
|
205
|
+
// Wrap a C++ exception class that inherits from std::runtime_error
|
|
206
|
+
// The second template parameter specifies the base class
|
|
207
|
+
rb_cBmpException = define_class_under<bmp::Exception, std::runtime_error>(rb_mBmp, "Exception")
|
|
208
|
+
.define_constructor(Constructor<bmp::Exception, const std::string&>(),
|
|
209
|
+
Arg("message"));
|
|
210
|
+
|
|
211
|
+
// ============================================================================
|
|
212
|
+
// MAIN CLASS: Bitmap
|
|
213
|
+
// ============================================================================
|
|
214
|
+
// This demonstrates most Rice features in one comprehensive class binding
|
|
215
|
+
rb_cBmpBitmap = define_class_under<bmp::Bitmap>(rb_mBmp, "Bitmap")
|
|
216
|
+
|
|
217
|
+
// --------------------------------------------------------------------
|
|
218
|
+
// CONSTRUCTORS
|
|
219
|
+
// --------------------------------------------------------------------
|
|
220
|
+
.define_constructor(Constructor<bmp::Bitmap>()) // Empty bitmap
|
|
221
|
+
|
|
222
|
+
.define_constructor(Constructor<bmp::Bitmap, const std::string&>(),
|
|
223
|
+
Arg("filename")) // Load from file
|
|
224
|
+
|
|
225
|
+
.define_constructor(Constructor<bmp::Bitmap, const std::int32_t, const std::int32_t>(),
|
|
226
|
+
Arg("width"), Arg("height")) // Create with dimensions
|
|
227
|
+
|
|
228
|
+
.define_constructor(Constructor<bmp::Bitmap, const bmp::Bitmap&>(),
|
|
229
|
+
Arg("other")) // Copy constructor
|
|
230
|
+
|
|
231
|
+
// --------------------------------------------------------------------
|
|
232
|
+
// DRAWING METHODS
|
|
233
|
+
// --------------------------------------------------------------------
|
|
234
|
+
.define_method("draw_line", &bmp::Bitmap::draw_line,
|
|
235
|
+
Arg("x1"), Arg("y1"), Arg("x2"), Arg("y2"), Arg("color"))
|
|
236
|
+
|
|
237
|
+
.define_method("fill_rect", &bmp::Bitmap::fill_rect,
|
|
238
|
+
Arg("x"), Arg("y"), Arg("width"), Arg("height"), Arg("color"))
|
|
239
|
+
|
|
240
|
+
.define_method("draw_rect", &bmp::Bitmap::draw_rect,
|
|
241
|
+
Arg("x"), Arg("y"), Arg("width"), Arg("height"), Arg("color"))
|
|
242
|
+
|
|
243
|
+
.define_method("draw_triangle", &bmp::Bitmap::draw_triangle,
|
|
244
|
+
Arg("x1"), Arg("y1"), Arg("x2"), Arg("y2"), Arg("x3"), Arg("y3"), Arg("color"))
|
|
245
|
+
|
|
246
|
+
.define_method("fill_triangle", &bmp::Bitmap::fill_triangle,
|
|
247
|
+
Arg("x1"), Arg("y1"), Arg("x2"), Arg("y2"), Arg("x3"), Arg("y3"), Arg("color"))
|
|
248
|
+
|
|
249
|
+
.define_method("draw_circle", &bmp::Bitmap::draw_circle,
|
|
250
|
+
Arg("center_x"), Arg("center_y"), Arg("radius"), Arg("color"))
|
|
251
|
+
|
|
252
|
+
.define_method("fill_circle", &bmp::Bitmap::fill_circle,
|
|
253
|
+
Arg("center_x"), Arg("center_y"), Arg("radius"), Arg("color"))
|
|
254
|
+
|
|
255
|
+
// --------------------------------------------------------------------
|
|
256
|
+
// OVERLOADED METHODS
|
|
257
|
+
// --------------------------------------------------------------------
|
|
258
|
+
// When a C++ class has overloaded methods (same name, different signatures),
|
|
259
|
+
// use template syntax to specify which overload to bind.
|
|
260
|
+
// The template parameter is: ReturnType(Class::*)(ArgTypes...) [const]
|
|
261
|
+
|
|
262
|
+
// Non-const version (returns mutable reference)
|
|
263
|
+
.define_method<bmp::Pixel&(bmp::Bitmap::*)(const std::int32_t, const std::int32_t)>(
|
|
264
|
+
"get", &bmp::Bitmap::get,
|
|
265
|
+
Arg("x"), Arg("y"))
|
|
266
|
+
|
|
267
|
+
// Const version (returns const reference)
|
|
268
|
+
.define_method<const bmp::Pixel&(bmp::Bitmap::*)(const std::int32_t, const std::int32_t) const>(
|
|
269
|
+
"get", &bmp::Bitmap::get,
|
|
270
|
+
Arg("x"), Arg("y"))
|
|
271
|
+
|
|
272
|
+
// --------------------------------------------------------------------
|
|
273
|
+
// SIMPLE ACCESSOR METHODS
|
|
274
|
+
// --------------------------------------------------------------------
|
|
275
|
+
.define_method("width", &bmp::Bitmap::width)
|
|
276
|
+
.define_method("height", &bmp::Bitmap::height)
|
|
277
|
+
|
|
278
|
+
// --------------------------------------------------------------------
|
|
279
|
+
// METHOD WITH DEFAULT ARGUMENT
|
|
280
|
+
// --------------------------------------------------------------------
|
|
281
|
+
// Use Arg("name") = value syntax for default arguments
|
|
282
|
+
.define_method("clear", &bmp::Bitmap::clear,
|
|
283
|
+
Arg("pixel") = static_cast<const bmp::Pixel>(bmp::Black))
|
|
284
|
+
|
|
285
|
+
// --------------------------------------------------------------------
|
|
286
|
+
// OPERATOR[] (array access)
|
|
287
|
+
// --------------------------------------------------------------------
|
|
288
|
+
// Overloaded [] operator - bind both const and non-const versions
|
|
289
|
+
.define_method<const bmp::Pixel&(bmp::Bitmap::*)(const std::size_t) const>(
|
|
290
|
+
"[]", &bmp::Bitmap::operator[],
|
|
291
|
+
Arg("i"))
|
|
292
|
+
|
|
293
|
+
.define_method<bmp::Pixel&(bmp::Bitmap::*)(const std::size_t)>(
|
|
294
|
+
"[]", &bmp::Bitmap::operator[],
|
|
295
|
+
Arg("i"))
|
|
296
|
+
|
|
297
|
+
// --------------------------------------------------------------------
|
|
298
|
+
// OPERATOR[]= (array assignment) - REQUIRES LAMBDA
|
|
299
|
+
// --------------------------------------------------------------------
|
|
300
|
+
// C++ doesn't have a separate []= operator, so we use a lambda
|
|
301
|
+
// This allows: bitmap[index] = pixel
|
|
302
|
+
.define_method("[]=", [](bmp::Bitmap& self, int index, bmp::Pixel& value)
|
|
303
|
+
{
|
|
304
|
+
self[index] = value;
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
// --------------------------------------------------------------------
|
|
308
|
+
// OTHER OPERATORS
|
|
309
|
+
// --------------------------------------------------------------------
|
|
310
|
+
.define_method("!", &bmp::Bitmap::operator!) // Check if empty
|
|
311
|
+
|
|
312
|
+
.define_method("==", &bmp::Bitmap::operator==,
|
|
313
|
+
Arg("image"))
|
|
314
|
+
|
|
315
|
+
.define_method("!=", &bmp::Bitmap::operator!=,
|
|
316
|
+
Arg("image"))
|
|
317
|
+
|
|
318
|
+
// Assignment operator (can't use = in Ruby, so use "assign")
|
|
319
|
+
.define_method<bmp::Bitmap&(bmp::Bitmap::*)(const bmp::Bitmap&)>(
|
|
320
|
+
"assign", &bmp::Bitmap::operator=,
|
|
321
|
+
Arg("image"))
|
|
322
|
+
|
|
323
|
+
.define_method<bmp::Bitmap&(bmp::Bitmap::*)(bmp::Bitmap&&) noexcept>(
|
|
324
|
+
"assign", &bmp::Bitmap::operator=,
|
|
325
|
+
Arg("image"))
|
|
326
|
+
|
|
327
|
+
// --------------------------------------------------------------------
|
|
328
|
+
// ITERATORS
|
|
329
|
+
// --------------------------------------------------------------------
|
|
330
|
+
// Rice can wrap C++ iterators to work with Ruby's each method
|
|
331
|
+
// This allows: bitmap.each { |pixel| ... }
|
|
332
|
+
.define_iterator<std::vector<bmp::Pixel>::iterator(bmp::Bitmap::*)() noexcept>(
|
|
333
|
+
&bmp::Bitmap::begin, &bmp::Bitmap::end, "each")
|
|
334
|
+
|
|
335
|
+
// Const iterator
|
|
336
|
+
.define_iterator<std::vector<bmp::Pixel>::const_iterator(bmp::Bitmap::*)() const noexcept>(
|
|
337
|
+
&bmp::Bitmap::cbegin, &bmp::Bitmap::cend, "each_const")
|
|
338
|
+
|
|
339
|
+
// Reverse iterator: bitmap.each_reverse { |pixel| ... }
|
|
340
|
+
.define_iterator<std::vector<bmp::Pixel>::reverse_iterator(bmp::Bitmap::*)() noexcept>(
|
|
341
|
+
&bmp::Bitmap::rbegin, &bmp::Bitmap::rend, "each_reverse")
|
|
342
|
+
|
|
343
|
+
// Reverse const iterator: bitmap.each_reverse { |pixel| ... }
|
|
344
|
+
.define_iterator<std::vector<bmp::Pixel>::const_reverse_iterator(bmp::Bitmap::*)() const noexcept>(
|
|
345
|
+
&bmp::Bitmap::crbegin, &bmp::Bitmap::crend, "each_const_reverse")
|
|
346
|
+
|
|
347
|
+
// --------------------------------------------------------------------
|
|
348
|
+
// MODIFIER METHODS
|
|
349
|
+
// --------------------------------------------------------------------
|
|
350
|
+
.define_method("set", &bmp::Bitmap::set,
|
|
351
|
+
Arg("x"), Arg("y"), Arg("color"))
|
|
352
|
+
|
|
353
|
+
// --------------------------------------------------------------------
|
|
354
|
+
// TRANSFORMATION METHODS (return new Bitmap)
|
|
355
|
+
// --------------------------------------------------------------------
|
|
356
|
+
.define_method("flip_v", &bmp::Bitmap::flip_v)
|
|
357
|
+
.define_method("flip_h", &bmp::Bitmap::flip_h)
|
|
358
|
+
.define_method("rotate_90_left", &bmp::Bitmap::rotate_90_left)
|
|
359
|
+
.define_method("rotate_90_right", &bmp::Bitmap::rotate_90_right)
|
|
360
|
+
|
|
361
|
+
// --------------------------------------------------------------------
|
|
362
|
+
// FILE I/O METHODS
|
|
363
|
+
// --------------------------------------------------------------------
|
|
364
|
+
// std::filesystem::path is automatically converted from Ruby strings
|
|
365
|
+
.define_method("save", &bmp::Bitmap::save,
|
|
366
|
+
Arg("filename"))
|
|
367
|
+
|
|
368
|
+
.define_method("load", &bmp::Bitmap::load,
|
|
369
|
+
Arg("filename"))
|
|
370
|
+
|
|
371
|
+
// --------------------------------------------------------------------
|
|
372
|
+
// INSPECT AND TO_S for debugging
|
|
373
|
+
// --------------------------------------------------------------------
|
|
374
|
+
.define_method("inspect", [](const bmp::Bitmap& self) -> std::string
|
|
375
|
+
{
|
|
376
|
+
return "#<Bmp::Bitmap " + std::to_string(self.width()) + "x" +
|
|
377
|
+
std::to_string(self.height()) + ">";
|
|
378
|
+
})
|
|
379
|
+
|
|
380
|
+
.define_method("to_s", [](const bmp::Bitmap& self) -> std::string
|
|
381
|
+
{
|
|
382
|
+
return "Bitmap(" + std::to_string(self.width()) + ", " +
|
|
383
|
+
std::to_string(self.height()) + ")";
|
|
384
|
+
})
|
|
385
|
+
|
|
386
|
+
// SIZE method for convenience
|
|
387
|
+
.define_method("size", [](const bmp::Bitmap& self) -> std::size_t
|
|
388
|
+
{
|
|
389
|
+
return static_cast<std::size_t>(self.width()) * static_cast<std::size_t>(self.height());
|
|
390
|
+
})
|
|
391
|
+
|
|
392
|
+
// EMPTY? method
|
|
393
|
+
.define_method("empty?", [](const bmp::Bitmap& self) -> bool
|
|
394
|
+
{
|
|
395
|
+
return !self; // Uses operator!
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Ruby Extension Entry Point
|
|
401
|
+
*
|
|
402
|
+
* This function is called by Ruby when the extension is loaded via 'require'.
|
|
403
|
+
* The function name MUST be Init_<extension_name> where <extension_name>
|
|
404
|
+
* matches the name in create_makefile() in extconf.rb.
|
|
405
|
+
*
|
|
406
|
+
* Rice::detail::cpp_protect() wraps the initialization in exception handling,
|
|
407
|
+
* converting any C++ exceptions to Ruby exceptions.
|
|
408
|
+
*/
|
|
409
|
+
extern "C"
|
|
410
|
+
void Init_bitmap_plus_plus_ruby()
|
|
411
|
+
{
|
|
412
|
+
Rice::detail::cpp_protect([]
|
|
413
|
+
{
|
|
414
|
+
// Setup Ruby bindings
|
|
415
|
+
initialize();
|
|
416
|
+
|
|
417
|
+
// Setup introspection support to generate RBS signatures and documentation
|
|
418
|
+
Init_Rice_Api();
|
|
419
|
+
});
|
|
420
|
+
}
|