ruby2d 0.10.0 → 0.11.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/ext/ruby2d/extconf.rb +31 -23
- data/ext/ruby2d/font.c +35 -0
- data/ext/ruby2d/gl.c +8 -57
- data/ext/ruby2d/gl2.c +8 -83
- data/ext/ruby2d/gl3.c +57 -115
- data/ext/ruby2d/gles.c +11 -85
- data/ext/ruby2d/image.c +16 -96
- data/ext/ruby2d/ruby2d.c +178 -305
- data/ext/ruby2d/ruby2d.h +16 -153
- data/ext/ruby2d/sound.c +1 -1
- data/ext/ruby2d/text.c +10 -117
- data/ext/ruby2d/window.c +4 -4
- data/lib/ruby2d/circle.rb +3 -1
- data/lib/ruby2d/cli/build.rb +2 -0
- data/lib/ruby2d/font.rb +20 -1
- data/lib/ruby2d/image.rb +22 -17
- data/lib/ruby2d/line.rb +3 -1
- data/lib/ruby2d/quad.rb +3 -1
- data/lib/ruby2d/rectangle.rb +1 -1
- data/lib/ruby2d/renderable.rb +0 -12
- data/lib/ruby2d/sound.rb +25 -0
- data/lib/ruby2d/sprite.rb +37 -87
- data/lib/ruby2d/square.rb +1 -1
- data/lib/ruby2d/text.rb +42 -20
- data/lib/ruby2d/texture.rb +28 -0
- data/lib/ruby2d/tileset.rb +40 -22
- data/lib/ruby2d/triangle.rb +3 -1
- data/lib/ruby2d/version.rb +1 -1
- data/lib/ruby2d/vertices.rb +84 -0
- data/lib/ruby2d/window.rb +13 -3
- data/lib/ruby2d.rb +2 -0
- metadata +6 -5
- data/ext/ruby2d/sprite.c +0 -147
- data/ext/ruby2d/tileset.c +0 -30
@@ -0,0 +1,28 @@
|
|
1
|
+
# Ruby2D::Text
|
2
|
+
|
3
|
+
module Ruby2D
|
4
|
+
class Texture
|
5
|
+
attr_reader :width, :height, :texture_id
|
6
|
+
|
7
|
+
def initialize(pixel_data, width, height)
|
8
|
+
@pixel_data = pixel_data
|
9
|
+
@width = width
|
10
|
+
@height = height
|
11
|
+
@texture_id = 0
|
12
|
+
end
|
13
|
+
|
14
|
+
def draw(coordinates, texture_coordinates, color)
|
15
|
+
if @texture_id == 0
|
16
|
+
@texture_id = ext_create(@pixel_data, @width, @height)
|
17
|
+
@pixel_data = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
color = [color.r, color.g, color.b, color.a]
|
21
|
+
ext_draw(coordinates, texture_coordinates, color, @texture_id)
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete
|
25
|
+
ext_delete(@texture_id)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/ruby2d/tileset.rb
CHANGED
@@ -5,26 +5,27 @@ module Ruby2D
|
|
5
5
|
include Renderable
|
6
6
|
|
7
7
|
def initialize(path, opts = {})
|
8
|
-
unless File.exist? path
|
9
|
-
raise Error, "Cannot find tileset image file `#{path}`"
|
10
|
-
end
|
11
8
|
@path = path
|
9
|
+
|
10
|
+
# Initialize the tileset texture
|
11
|
+
@texture = Texture.new(*Image.load_image(@path))
|
12
|
+
@width = opts[:width] || @texture.width
|
13
|
+
@height = opts[:height] || @texture.height
|
14
|
+
@z = opts[:z] || 0
|
15
|
+
|
12
16
|
@tiles = []
|
13
17
|
@defined_tiles = {}
|
14
18
|
@padding = opts[:padding] || 0
|
15
19
|
@spacing = opts[:spacing] || 0
|
16
20
|
@tile_width = opts[:tile_width]
|
17
21
|
@tile_height = opts[:tile_height]
|
18
|
-
|
19
|
-
unless ext_init(@path)
|
20
|
-
raise Error, "Tileset `#{@path}` cannot be created"
|
21
|
-
end
|
22
|
+
@scale = opts[:scale] || 1
|
22
23
|
|
23
24
|
unless opts[:show] == false then add end
|
24
25
|
end
|
25
26
|
|
26
|
-
def define_tile(name, x, y)
|
27
|
-
@defined_tiles[name] = { x: x, y: y }
|
27
|
+
def define_tile(name, x, y, rotate: 0, flip: nil)
|
28
|
+
@defined_tiles[name] = { x: x, y: y , rotate: rotate, flip: flip }
|
28
29
|
end
|
29
30
|
|
30
31
|
def set_tile(name, coordinates)
|
@@ -34,6 +35,8 @@ module Ruby2D
|
|
34
35
|
@tiles.push({
|
35
36
|
tile_x: tile.fetch(:x),
|
36
37
|
tile_y: tile.fetch(:y),
|
38
|
+
tile_rotate: tile.fetch(:rotate),
|
39
|
+
tile_flip: tile.fetch(:flip),
|
37
40
|
x: coordinate.fetch(:x),
|
38
41
|
y: coordinate.fetch(:y)
|
39
42
|
})
|
@@ -45,25 +48,40 @@ module Ruby2D
|
|
45
48
|
end
|
46
49
|
end
|
47
50
|
|
48
|
-
def draw
|
49
|
-
|
51
|
+
def draw
|
52
|
+
Window.render_ready_check
|
53
|
+
|
54
|
+
render
|
50
55
|
end
|
51
56
|
|
52
57
|
private
|
53
58
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
+
|
60
|
+
def render
|
61
|
+
scaled_padding = @padding * @scale
|
62
|
+
scaled_spacing = @spacing * @scale
|
63
|
+
scaled_tile_width = @tile_width * @scale
|
64
|
+
scaled_tile_height = @tile_height * @scale
|
65
|
+
scaled_width = @width * @scale
|
66
|
+
scaled_height = @height * @scale
|
59
67
|
|
60
68
|
@tiles.each do |tile|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
69
|
+
crop = {
|
70
|
+
x: scaled_padding + (tile.fetch(:tile_x) * (scaled_spacing + scaled_tile_width)),
|
71
|
+
y: scaled_padding + (tile.fetch(:tile_y) * (scaled_spacing + scaled_tile_height)),
|
72
|
+
width: scaled_tile_width,
|
73
|
+
height: scaled_tile_height,
|
74
|
+
image_width: scaled_width,
|
75
|
+
image_height: scaled_height,
|
76
|
+
}
|
77
|
+
|
78
|
+
color = defined?(@color) ? @color : Color.new([1.0, 1.0, 1.0, 1.0])
|
79
|
+
|
80
|
+
vertices = Vertices.new(tile.fetch(:x), tile.fetch(:y), scaled_tile_width, scaled_tile_height, tile.fetch(:tile_rotate), crop: crop, flip: tile.fetch(:tile_flip))
|
81
|
+
|
82
|
+
@texture.draw(
|
83
|
+
vertices.coordinates, vertices.texture_coordinates, color
|
84
|
+
)
|
67
85
|
end
|
68
86
|
end
|
69
87
|
end
|
data/lib/ruby2d/triangle.rb
CHANGED
@@ -17,7 +17,7 @@ module Ruby2D
|
|
17
17
|
@y3 = opts[:y3] || 100
|
18
18
|
@z = opts[:z] || 0
|
19
19
|
self.color = opts[:color] || 'white'
|
20
|
-
self.opacity = opts[:opacity] if opts[:opacity]
|
20
|
+
self.color.opacity = opts[:opacity] if opts[:opacity]
|
21
21
|
add
|
22
22
|
end
|
23
23
|
|
@@ -39,6 +39,8 @@ module Ruby2D
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def self.draw(opts = {})
|
42
|
+
Window.render_ready_check
|
43
|
+
|
42
44
|
ext_draw([
|
43
45
|
opts[:x1], opts[:y1], opts[:color][0][0], opts[:color][0][1], opts[:color][0][2], opts[:color][0][3],
|
44
46
|
opts[:x2], opts[:y2], opts[:color][1][0], opts[:color][1][1], opts[:color][1][2], opts[:color][1][3],
|
data/lib/ruby2d/version.rb
CHANGED
@@ -0,0 +1,84 @@
|
|
1
|
+
# Ruby2D::Vertices
|
2
|
+
|
3
|
+
# This class generates a vertices array which are passed to the openGL rendering code.
|
4
|
+
# The vertices array is split up into 4 groups (1 - top left, 2 - top right, 3 - bottom right, 4 - bottom left)
|
5
|
+
# This class is responsible for transforming textures, it can scale / crop / rotate and flip textures
|
6
|
+
|
7
|
+
module Ruby2D
|
8
|
+
class Vertices
|
9
|
+
def initialize(x, y, width, height, rotate, crop: nil, flip: nil)
|
10
|
+
@flip = flip
|
11
|
+
@x = x
|
12
|
+
@y = y
|
13
|
+
@width = width.to_f
|
14
|
+
@height = height.to_f
|
15
|
+
|
16
|
+
if @flip == :horizontal || @flip == :both
|
17
|
+
@x = @x + @width
|
18
|
+
@width = -@width
|
19
|
+
end
|
20
|
+
|
21
|
+
if @flip == :vertical || @flip == :both
|
22
|
+
@y = y + @height
|
23
|
+
@height = -@height
|
24
|
+
end
|
25
|
+
|
26
|
+
@rotate = rotate
|
27
|
+
@rx = @x + (@width / 2.0)
|
28
|
+
@ry = @y + (@height / 2.0)
|
29
|
+
@crop = crop
|
30
|
+
end
|
31
|
+
|
32
|
+
def coordinates
|
33
|
+
x1, y1 = rotate(@x, @y); # Top left
|
34
|
+
x2, y2 = rotate(@x + @width, @y); # Top right
|
35
|
+
x3, y3 = rotate(@x + @width, @y + @height); # Bottom right
|
36
|
+
x4, y4 = rotate(@x, @y + @height); # Bottom left
|
37
|
+
|
38
|
+
[ x1, y1, x2, y2, x3, y3, x4, y4 ]
|
39
|
+
end
|
40
|
+
|
41
|
+
def texture_coordinates
|
42
|
+
if @crop.nil?
|
43
|
+
tx1 = 0.0; ty1 = 0.0 # Top left
|
44
|
+
tx2 = 1.0; ty2 = 0.0 # Top right
|
45
|
+
tx3 = 1.0; ty3 = 1.0 # Bottom right
|
46
|
+
tx4 = 0.0; ty4 = 1.0 # Bottom left
|
47
|
+
else
|
48
|
+
tx1 = @crop[:x] / @crop[:image_width].to_f; ty1 = @crop[:y] / @crop[:image_height].to_f # Top left
|
49
|
+
tx2 = tx1 + (@crop[:width] / @crop[:image_width].to_f); ty2 = ty1 # Top right
|
50
|
+
tx3 = tx2; ty3 = ty1 + (@crop[:height] / @crop[:image_height].to_f) # Botttom right
|
51
|
+
tx4 = tx1; ty4 = ty3 # Bottom left
|
52
|
+
end
|
53
|
+
|
54
|
+
[ tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4 ]
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def rotate(x, y)
|
60
|
+
return [x, y] if @rotate == 0
|
61
|
+
|
62
|
+
# Convert from degrees to radians
|
63
|
+
angle = @rotate * Math::PI / 180.0
|
64
|
+
|
65
|
+
# Get the sine and cosine of the angle
|
66
|
+
sa = Math.sin(angle)
|
67
|
+
ca = Math.cos(angle)
|
68
|
+
|
69
|
+
# Translate point to origin
|
70
|
+
x -= @rx
|
71
|
+
y -= @ry
|
72
|
+
|
73
|
+
# Rotate point
|
74
|
+
xnew = x * ca - y * sa;
|
75
|
+
ynew = x * sa + y * ca;
|
76
|
+
|
77
|
+
# Translate point back
|
78
|
+
x = xnew + @rx;
|
79
|
+
y = ynew + @ry;
|
80
|
+
|
81
|
+
[x, y]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/ruby2d/window.rb
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
|
5
5
|
module Ruby2D
|
6
6
|
class Window
|
7
|
+
@@open_window = false
|
7
8
|
|
8
9
|
# Event structures
|
9
10
|
EventDescriptor = Struct.new(:type, :id)
|
@@ -109,9 +110,7 @@ module Ruby2D
|
|
109
110
|
@render_proc = Proc.new {}
|
110
111
|
|
111
112
|
# Detect if window is being used through the DSL or as a class instance
|
112
|
-
|
113
|
-
@using_dsl = true
|
114
|
-
end
|
113
|
+
@using_dsl = !(method(:update).parameters.empty? || method(:render).parameters.empty?)
|
115
114
|
|
116
115
|
# Whether diagnostic messages should be printed
|
117
116
|
@diagnostics = false
|
@@ -190,6 +189,12 @@ module Ruby2D
|
|
190
189
|
def close
|
191
190
|
DSL.window.close
|
192
191
|
end
|
192
|
+
|
193
|
+
def render_ready_check
|
194
|
+
unless @@open_window
|
195
|
+
raise Error, "Attempting to draw before the window is ready. Please put calls to draw() inside of a render block."
|
196
|
+
end
|
197
|
+
end
|
193
198
|
end
|
194
199
|
|
195
200
|
# Public instance methods
|
@@ -616,6 +621,11 @@ module Ruby2D
|
|
616
621
|
|
617
622
|
# Show the window
|
618
623
|
def show
|
624
|
+
if @@open_window
|
625
|
+
raise Error, "Window#show called multiple times, Ruby2D only supports a single open window"
|
626
|
+
end
|
627
|
+
|
628
|
+
@@open_window = true
|
619
629
|
ext_show
|
620
630
|
end
|
621
631
|
|
data/lib/ruby2d.rb
CHANGED
@@ -22,6 +22,8 @@ unless RUBY_ENGINE == 'mruby'
|
|
22
22
|
require 'ruby2d/text'
|
23
23
|
require 'ruby2d/sound'
|
24
24
|
require 'ruby2d/music'
|
25
|
+
require 'ruby2d/texture'
|
26
|
+
require 'ruby2d/vertices'
|
25
27
|
|
26
28
|
if defined?(RubyInstaller)
|
27
29
|
s2d_dll_path = Gem::Specification.find_by_name('ruby2d').gem_dir + '/assets/mingw/bin'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby2d
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom Black
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-07
|
11
|
+
date: 2021-09-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -274,6 +274,7 @@ files:
|
|
274
274
|
- ext/ruby2d/common.c
|
275
275
|
- ext/ruby2d/controllers.c
|
276
276
|
- ext/ruby2d/extconf.rb
|
277
|
+
- ext/ruby2d/font.c
|
277
278
|
- ext/ruby2d/gl.c
|
278
279
|
- ext/ruby2d/gl2.c
|
279
280
|
- ext/ruby2d/gl3.c
|
@@ -285,9 +286,7 @@ files:
|
|
285
286
|
- ext/ruby2d/ruby2d.h
|
286
287
|
- ext/ruby2d/shapes.c
|
287
288
|
- ext/ruby2d/sound.c
|
288
|
-
- ext/ruby2d/sprite.c
|
289
289
|
- ext/ruby2d/text.c
|
290
|
-
- ext/ruby2d/tileset.c
|
291
290
|
- ext/ruby2d/window.c
|
292
291
|
- lib/ruby2d.rb
|
293
292
|
- lib/ruby2d/circle.rb
|
@@ -312,9 +311,11 @@ files:
|
|
312
311
|
- lib/ruby2d/sprite.rb
|
313
312
|
- lib/ruby2d/square.rb
|
314
313
|
- lib/ruby2d/text.rb
|
314
|
+
- lib/ruby2d/texture.rb
|
315
315
|
- lib/ruby2d/tileset.rb
|
316
316
|
- lib/ruby2d/triangle.rb
|
317
317
|
- lib/ruby2d/version.rb
|
318
|
+
- lib/ruby2d/vertices.rb
|
318
319
|
- lib/ruby2d/window.rb
|
319
320
|
homepage: http://www.ruby2d.com
|
320
321
|
licenses:
|
@@ -335,7 +336,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
335
336
|
- !ruby/object:Gem::Version
|
336
337
|
version: '0'
|
337
338
|
requirements: []
|
338
|
-
rubygems_version: 3.2.
|
339
|
+
rubygems_version: 3.2.27
|
339
340
|
signing_key:
|
340
341
|
specification_version: 4
|
341
342
|
summary: Ruby 2D
|
data/ext/ruby2d/sprite.c
DELETED
@@ -1,147 +0,0 @@
|
|
1
|
-
// sprite.c
|
2
|
-
|
3
|
-
#include "ruby2d.h"
|
4
|
-
|
5
|
-
|
6
|
-
/*
|
7
|
-
* Create a sprite, given an image file path
|
8
|
-
*/
|
9
|
-
R2D_Sprite *R2D_CreateSprite(const char *path) {
|
10
|
-
|
11
|
-
// Check if image file exists
|
12
|
-
if (!R2D_FileExists(path)) {
|
13
|
-
R2D_Error("R2D_CreateSprite", "Sprite image file `%s` not found", path);
|
14
|
-
return NULL;
|
15
|
-
}
|
16
|
-
|
17
|
-
// Allocate the sprite structure
|
18
|
-
R2D_Sprite *spr = (R2D_Sprite *) malloc(sizeof(R2D_Sprite));
|
19
|
-
if (!spr) {
|
20
|
-
R2D_Error("R2D_CreateSprite", "Out of memory!");
|
21
|
-
return NULL;
|
22
|
-
}
|
23
|
-
|
24
|
-
// Load the sprite image file
|
25
|
-
spr->img = R2D_CreateImage(path);
|
26
|
-
if (!spr->img) {
|
27
|
-
R2D_Error("R2D_CreateSprite", "Cannot create sprite image `%s`", path);
|
28
|
-
free(spr);
|
29
|
-
return NULL;
|
30
|
-
}
|
31
|
-
|
32
|
-
// Initialize values
|
33
|
-
spr->path = path;
|
34
|
-
spr->x = 0;
|
35
|
-
spr->y = 0;
|
36
|
-
spr->color.r = 1.f;
|
37
|
-
spr->color.g = 1.f;
|
38
|
-
spr->color.b = 1.f;
|
39
|
-
spr->color.a = 1.f;
|
40
|
-
spr->width = spr->img->width;
|
41
|
-
spr->height = spr->img->height;
|
42
|
-
spr->clip_width = spr->img->width;
|
43
|
-
spr->clip_height = spr->img->height;
|
44
|
-
spr->rotate = 0;
|
45
|
-
spr->rx = 0;
|
46
|
-
spr->ry = 0;
|
47
|
-
spr->tx1 = 0.f;
|
48
|
-
spr->ty1 = 0.f;
|
49
|
-
spr->tx2 = 1.f;
|
50
|
-
spr->ty2 = 0.f;
|
51
|
-
spr->tx3 = 1.f;
|
52
|
-
spr->ty3 = 1.f;
|
53
|
-
spr->tx4 = 0.f;
|
54
|
-
spr->ty4 = 1.f;
|
55
|
-
|
56
|
-
return spr;
|
57
|
-
}
|
58
|
-
|
59
|
-
|
60
|
-
/*
|
61
|
-
* Clip a sprite
|
62
|
-
*/
|
63
|
-
void R2D_ClipSprite(R2D_Sprite *spr, int x, int y, int w, int h) {
|
64
|
-
if (!spr) return;
|
65
|
-
|
66
|
-
// Calculate ratios
|
67
|
-
// rw = ratio width; rh = ratio height
|
68
|
-
double rw = w / (double)spr->img->width;
|
69
|
-
double rh = h / (double)spr->img->height;
|
70
|
-
|
71
|
-
// Apply ratios to x, y coordinates
|
72
|
-
// cx = crop x coord; cy = crop y coord
|
73
|
-
double cx = x * rw;
|
74
|
-
double cy = y * rh;
|
75
|
-
|
76
|
-
// Convert given width, height to doubles
|
77
|
-
// cw = crop width; ch = crop height
|
78
|
-
double cw = (double)w;
|
79
|
-
double ch = (double)h;
|
80
|
-
|
81
|
-
// Apply ratio to texture width and height
|
82
|
-
// tw = texture width; th = texture height
|
83
|
-
double tw = rw * w;
|
84
|
-
double th = rh * h;
|
85
|
-
|
86
|
-
// Calculate and store sprite texture values
|
87
|
-
|
88
|
-
spr->tx1 = cx / cw;
|
89
|
-
spr->ty1 = cy / ch;
|
90
|
-
|
91
|
-
spr->tx2 = (cx + tw) / cw;
|
92
|
-
spr->ty2 = cy / ch;
|
93
|
-
|
94
|
-
spr->tx3 = (cx + tw) / cw;
|
95
|
-
spr->ty3 = (cy + th) / ch;
|
96
|
-
|
97
|
-
spr->tx4 = cx / cw;
|
98
|
-
spr->ty4 = (cy + th) / ch;
|
99
|
-
|
100
|
-
// Store the sprite dimensions
|
101
|
-
spr->width = (spr->width / (double)spr->clip_width ) * w;
|
102
|
-
spr->height = (spr->height / (double)spr->clip_height) * h;
|
103
|
-
spr->clip_width = w;
|
104
|
-
spr->clip_height = h;
|
105
|
-
}
|
106
|
-
|
107
|
-
|
108
|
-
/*
|
109
|
-
* Rotate a sprite
|
110
|
-
*/
|
111
|
-
void R2D_RotateSprite(R2D_Sprite *spr, GLfloat angle, int position) {
|
112
|
-
|
113
|
-
R2D_GL_Point p = R2D_GetRectRotationPoint(
|
114
|
-
spr->x, spr->y, spr->width, spr->height, position
|
115
|
-
);
|
116
|
-
|
117
|
-
spr->rotate = angle;
|
118
|
-
spr->rx = p.x;
|
119
|
-
spr->ry = p.y;
|
120
|
-
}
|
121
|
-
|
122
|
-
|
123
|
-
/*
|
124
|
-
* Draw a sprite
|
125
|
-
*/
|
126
|
-
void R2D_DrawSprite(R2D_Sprite *spr) {
|
127
|
-
if (!spr) return;
|
128
|
-
|
129
|
-
if (spr->img->texture_id == 0) {
|
130
|
-
R2D_GL_CreateTexture(&spr->img->texture_id, spr->img->format,
|
131
|
-
spr->img->width, spr->img->height,
|
132
|
-
spr->img->surface->pixels, GL_NEAREST);
|
133
|
-
SDL_FreeSurface(spr->img->surface);
|
134
|
-
}
|
135
|
-
|
136
|
-
R2D_GL_DrawSprite(spr);
|
137
|
-
}
|
138
|
-
|
139
|
-
|
140
|
-
/*
|
141
|
-
* Free a sprite
|
142
|
-
*/
|
143
|
-
void R2D_FreeSprite(R2D_Sprite *spr) {
|
144
|
-
if (!spr) return;
|
145
|
-
R2D_FreeImage(spr->img);
|
146
|
-
free(spr);
|
147
|
-
}
|