texplay 0.4.3 → 0.4.4.pre
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 +225 -222
- data/README.markdown +48 -48
- data/Rakefile +16 -16
- data/examples/common.rb +18 -18
- data/examples/example_alpha_blend.rb +29 -29
- data/examples/example_bezier.rb +41 -41
- data/examples/example_blank.rb +37 -37
- data/examples/example_cache.rb +21 -21
- data/examples/example_color_control.rb +69 -69
- data/examples/example_color_transform.rb +62 -62
- data/examples/example_color_transform_circle.rb +34 -34
- data/examples/example_darken.rb +24 -24
- data/examples/example_dup.rb +73 -73
- data/examples/example_each.rb +39 -39
- data/examples/example_effect.rb +34 -34
- data/examples/example_fill.rb +43 -43
- data/examples/example_fill_old.rb +48 -48
- data/examples/example_fluent.rb +29 -29
- data/examples/example_font.rb +31 -31
- data/examples/example_hash_arguments.rb +46 -46
- data/examples/example_ippa.rb +23 -23
- data/examples/example_light.rb +75 -75
- data/examples/example_light_multiply.rb +18 -18
- data/examples/example_lsystem.rb +61 -61
- data/examples/example_melt.rb +25 -25
- data/examples/example_meyet.rb +62 -62
- data/examples/example_polyline.rb +42 -42
- data/examples/example_scale.rb +27 -27
- data/examples/example_select.rb +36 -36
- data/examples/example_select2.rb +25 -25
- data/examples/example_simple.rb +46 -46
- data/examples/example_splice.rb +26 -26
- data/examples/example_sync.rb +59 -59
- data/examples/example_tiles.rb +41 -41
- data/examples/example_trace.rb +22 -22
- data/examples/example_transparent.rb +28 -28
- data/examples/example_transparent2.rb +24 -24
- data/examples/example_transparent3.rb +20 -20
- data/examples/example_turtle.rb +39 -39
- data/examples/example_weird.rb +22 -22
- data/examples/example_window_render_to_image.rb +41 -41
- data/examples/example_window_to_blob.rb +35 -35
- data/examples/media/maria.png +0 -0
- data/examples/media/rose.bmp +0 -0
- data/ext/texplay/actions.c +1011 -1006
- data/ext/texplay/actions.h +60 -60
- data/ext/texplay/bindings.c +1130 -1125
- data/ext/texplay/bindings.h +46 -46
- data/ext/texplay/cache.c +123 -118
- data/ext/texplay/cache.h +24 -24
- data/ext/texplay/compat.h +21 -27
- data/ext/texplay/extconf.rb +38 -38
- data/ext/texplay/graphics_utils.c +1318 -1313
- data/ext/texplay/graphics_utils.h +22 -22
- data/ext/texplay/texplay.c +206 -201
- data/ext/texplay/texplay.h +153 -153
- data/ext/texplay/utils.c +896 -891
- data/ext/texplay/utils.h +153 -153
- data/lib/texplay-contrib.rb +147 -147
- data/lib/texplay.rb +347 -347
- data/lib/texplay/alone.rb +20 -20
- data/lib/texplay/c_function_docs.rb +178 -178
- data/lib/texplay/live.rb +84 -84
- data/lib/texplay/version.rb +3 -3
- data/live/live.rb +85 -85
- data/test/image_spec.rb +45 -45
- data/test/texplay_spec.rb +144 -144
- metadata +42 -52
- data/lib/texplay/1.8/texplay.so +0 -0
- data/lib/texplay/1.9/texplay.so +0 -0
data/ext/texplay/texplay.h
CHANGED
@@ -1,153 +1,153 @@
|
|
1
|
-
/* texplay.h (C) John Mair 2008
|
2
|
-
* This program is distributed under the terms of the MIT License
|
3
|
-
*
|
4
|
-
*
|
5
|
-
* */
|
6
|
-
|
7
|
-
#ifndef GUARD_TEXPLAY_H
|
8
|
-
#define GUARD_TEXPLAY_H
|
9
|
-
|
10
|
-
#include <ruby.h>
|
11
|
-
|
12
|
-
/* #defines */
|
13
|
-
#define OOB_VAL 9999
|
14
|
-
#define XMAX_OOB OOB_VAL
|
15
|
-
#define YMAX_OOB OOB_VAL
|
16
|
-
#define XMIN_OOB -OOB_VAL
|
17
|
-
#define YMIN_OOB -OOB_VAL
|
18
|
-
#define RGBA_LIST_SIZE 100
|
19
|
-
#define PI 3.14159265358979
|
20
|
-
|
21
|
-
/* macros */
|
22
|
-
#define SWAP(X, Y) {(X) ^= (Y); (Y) ^= (X); (X) ^= (Y);}
|
23
|
-
#define ROUND(X) (int)((X) + 0.5)
|
24
|
-
#define ARY_SIZE(X) sizeof(X) / sizeof(*X)
|
25
|
-
#define SGN(X) ((X) >= 0 ? 1 : -1)
|
26
|
-
#define MAX(X, Y) ((X) > (Y)) ? (X) :(Y)
|
27
|
-
#define MIN(X, Y) ((X) < (Y)) ? (X) : (Y)
|
28
|
-
#define ABS(X) ((X) >= 0 ? (X) : -(X))
|
29
|
-
|
30
|
-
/* enums */
|
31
|
-
typedef enum e_bool {
|
32
|
-
false, true
|
33
|
-
} bool;
|
34
|
-
|
35
|
-
typedef enum e_color {
|
36
|
-
red, green, blue, alpha
|
37
|
-
} color_t;
|
38
|
-
|
39
|
-
typedef enum e_sync_mode {
|
40
|
-
lazy_sync, eager_sync, no_sync
|
41
|
-
}
|
42
|
-
|
43
|
-
|
44
|
-
typedef enum {
|
45
|
-
clear, copy, noop,
|
46
|
-
set, copy_inverted,
|
47
|
-
invert, and_reverse, and,
|
48
|
-
or, nand, nor, xor,
|
49
|
-
equiv, and_inverted,
|
50
|
-
or_inverted, additive,
|
51
|
-
multiply, screen, overlay,
|
52
|
-
darken, lighten, color_dodge,
|
53
|
-
color_burn, hard_light, soft_light,
|
54
|
-
difference, exclusion
|
55
|
-
} draw_mode;
|
56
|
-
|
57
|
-
typedef enum {
|
58
|
-
source, dest, source_with_fixed_alpha, dest_with_fixed_alpha
|
59
|
-
} alpha_blend_mode_t;
|
60
|
-
|
61
|
-
/* structs */
|
62
|
-
typedef struct s_rgba {
|
63
|
-
float red, green, blue, alpha;
|
64
|
-
} rgba;
|
65
|
-
|
66
|
-
typedef struct {
|
67
|
-
rgba colors[RGBA_LIST_SIZE];
|
68
|
-
int size;
|
69
|
-
} rgba_list;
|
70
|
-
|
71
|
-
|
72
|
-
/* stores image data */
|
73
|
-
typedef struct {
|
74
|
-
int width, height;
|
75
|
-
float top, left;
|
76
|
-
int tname;
|
77
|
-
float * td_array;
|
78
|
-
int yincr, firstpixel;
|
79
|
-
int x_offset, y_offset;
|
80
|
-
VALUE image;
|
81
|
-
} texture_info;
|
82
|
-
|
83
|
-
|
84
|
-
/* convenience macro */
|
85
|
-
#define IMAGE_BOUNDS(X) ((image_bounds *) (X))
|
86
|
-
typedef struct {
|
87
|
-
int xmin;
|
88
|
-
int ymin;
|
89
|
-
int xmax;
|
90
|
-
int ymax;
|
91
|
-
} image_bounds;
|
92
|
-
|
93
|
-
|
94
|
-
typedef struct action_struct {
|
95
|
-
int xmin, ymin, xmax, ymax;
|
96
|
-
|
97
|
-
|
98
|
-
/* pointer to associated texture */
|
99
|
-
/* a bit of a kludge having this here
|
100
|
-
since it's only being used by convert_image_local_color_to_rgba */
|
101
|
-
texture_info * tex;
|
102
|
-
|
103
|
-
VALUE hash_arg;
|
104
|
-
|
105
|
-
/* action color */
|
106
|
-
rgba color;
|
107
|
-
|
108
|
-
/* pen data */
|
109
|
-
struct {
|
110
|
-
|
111
|
-
/* color control, dynamic */
|
112
|
-
bool has_color_control_proc;
|
113
|
-
VALUE color_control_proc;
|
114
|
-
int color_control_arity;
|
115
|
-
|
116
|
-
/* color control, static */
|
117
|
-
bool has_color_control_transform;
|
118
|
-
rgba color_mult;
|
119
|
-
rgba color_add;
|
120
|
-
|
121
|
-
/* texture fill */
|
122
|
-
bool has_source_texture;
|
123
|
-
texture_info source_tex;
|
124
|
-
|
125
|
-
/* lerp */
|
126
|
-
bool has_lerp;
|
127
|
-
float lerp;
|
128
|
-
|
129
|
-
/* alpha blend */
|
130
|
-
bool alpha_blend;
|
131
|
-
alpha_blend_mode_t alpha_blend_mode;
|
132
|
-
|
133
|
-
/* drawing mode */
|
134
|
-
bool has_drawing_mode;
|
135
|
-
draw_mode drawing_mode;
|
136
|
-
|
137
|
-
/* tolerance */
|
138
|
-
bool has_tolerance;
|
139
|
-
float tolerance;
|
140
|
-
|
141
|
-
/* color selection */
|
142
|
-
bool has_color_select;
|
143
|
-
rgba_list source_select;
|
144
|
-
rgba_list source_ignore;
|
145
|
-
rgba_list dest_select;
|
146
|
-
rgba_list dest_ignore;
|
147
|
-
|
148
|
-
} pen;
|
149
|
-
|
150
|
-
} action_struct;
|
151
|
-
|
152
|
-
|
153
|
-
#endif
|
1
|
+
/* texplay.h (C) John Mair 2008
|
2
|
+
* This program is distributed under the terms of the MIT License
|
3
|
+
*
|
4
|
+
*
|
5
|
+
* */
|
6
|
+
|
7
|
+
#ifndef GUARD_TEXPLAY_H
|
8
|
+
#define GUARD_TEXPLAY_H
|
9
|
+
|
10
|
+
#include <ruby.h>
|
11
|
+
|
12
|
+
/* #defines */
|
13
|
+
#define OOB_VAL 9999
|
14
|
+
#define XMAX_OOB OOB_VAL
|
15
|
+
#define YMAX_OOB OOB_VAL
|
16
|
+
#define XMIN_OOB -OOB_VAL
|
17
|
+
#define YMIN_OOB -OOB_VAL
|
18
|
+
#define RGBA_LIST_SIZE 100
|
19
|
+
#define PI 3.14159265358979
|
20
|
+
|
21
|
+
/* macros */
|
22
|
+
#define SWAP(X, Y) {(X) ^= (Y); (Y) ^= (X); (X) ^= (Y);}
|
23
|
+
#define ROUND(X) (int)((X) + 0.5)
|
24
|
+
#define ARY_SIZE(X) sizeof(X) / sizeof(*X)
|
25
|
+
#define SGN(X) ((X) >= 0 ? 1 : -1)
|
26
|
+
#define MAX(X, Y) ((X) > (Y)) ? (X) :(Y)
|
27
|
+
#define MIN(X, Y) ((X) < (Y)) ? (X) : (Y)
|
28
|
+
#define ABS(X) ((X) >= 0 ? (X) : -(X))
|
29
|
+
|
30
|
+
/* enums */
|
31
|
+
typedef enum e_bool {
|
32
|
+
false, true
|
33
|
+
} bool;
|
34
|
+
|
35
|
+
typedef enum e_color {
|
36
|
+
red, green, blue, alpha
|
37
|
+
} color_t;
|
38
|
+
|
39
|
+
typedef enum e_sync_mode {
|
40
|
+
lazy_sync, eager_sync, no_sync
|
41
|
+
} sync_;
|
42
|
+
|
43
|
+
|
44
|
+
typedef enum {
|
45
|
+
clear, copy, noop,
|
46
|
+
set, copy_inverted,
|
47
|
+
invert, and_reverse, and,
|
48
|
+
or, nand, nor, xor,
|
49
|
+
equiv, and_inverted,
|
50
|
+
or_inverted, additive,
|
51
|
+
multiply, screen, overlay,
|
52
|
+
darken, lighten, color_dodge,
|
53
|
+
color_burn, hard_light, soft_light,
|
54
|
+
difference, exclusion
|
55
|
+
} draw_mode;
|
56
|
+
|
57
|
+
typedef enum {
|
58
|
+
source, dest, source_with_fixed_alpha, dest_with_fixed_alpha
|
59
|
+
} alpha_blend_mode_t;
|
60
|
+
|
61
|
+
/* structs */
|
62
|
+
typedef struct s_rgba {
|
63
|
+
float red, green, blue, alpha;
|
64
|
+
} rgba;
|
65
|
+
|
66
|
+
typedef struct {
|
67
|
+
rgba colors[RGBA_LIST_SIZE];
|
68
|
+
int size;
|
69
|
+
} rgba_list;
|
70
|
+
|
71
|
+
|
72
|
+
/* stores image data */
|
73
|
+
typedef struct {
|
74
|
+
int width, height;
|
75
|
+
float top, left;
|
76
|
+
int tname;
|
77
|
+
float * td_array;
|
78
|
+
int yincr, firstpixel;
|
79
|
+
int x_offset, y_offset;
|
80
|
+
VALUE image;
|
81
|
+
} texture_info;
|
82
|
+
|
83
|
+
|
84
|
+
/* convenience macro */
|
85
|
+
#define IMAGE_BOUNDS(X) ((image_bounds *) (X))
|
86
|
+
typedef struct {
|
87
|
+
int xmin;
|
88
|
+
int ymin;
|
89
|
+
int xmax;
|
90
|
+
int ymax;
|
91
|
+
} image_bounds;
|
92
|
+
|
93
|
+
|
94
|
+
typedef struct action_struct {
|
95
|
+
int xmin, ymin, xmax, ymax;
|
96
|
+
sync_ sync_mode;
|
97
|
+
|
98
|
+
/* pointer to associated texture */
|
99
|
+
/* a bit of a kludge having this here
|
100
|
+
since it's only being used by convert_image_local_color_to_rgba */
|
101
|
+
texture_info * tex;
|
102
|
+
|
103
|
+
VALUE hash_arg;
|
104
|
+
|
105
|
+
/* action color */
|
106
|
+
rgba color;
|
107
|
+
|
108
|
+
/* pen data */
|
109
|
+
struct {
|
110
|
+
|
111
|
+
/* color control, dynamic */
|
112
|
+
bool has_color_control_proc;
|
113
|
+
VALUE color_control_proc;
|
114
|
+
int color_control_arity;
|
115
|
+
|
116
|
+
/* color control, static */
|
117
|
+
bool has_color_control_transform;
|
118
|
+
rgba color_mult;
|
119
|
+
rgba color_add;
|
120
|
+
|
121
|
+
/* texture fill */
|
122
|
+
bool has_source_texture;
|
123
|
+
texture_info source_tex;
|
124
|
+
|
125
|
+
/* lerp */
|
126
|
+
bool has_lerp;
|
127
|
+
float lerp;
|
128
|
+
|
129
|
+
/* alpha blend */
|
130
|
+
bool alpha_blend;
|
131
|
+
alpha_blend_mode_t alpha_blend_mode;
|
132
|
+
|
133
|
+
/* drawing mode */
|
134
|
+
bool has_drawing_mode;
|
135
|
+
draw_mode drawing_mode;
|
136
|
+
|
137
|
+
/* tolerance */
|
138
|
+
bool has_tolerance;
|
139
|
+
float tolerance;
|
140
|
+
|
141
|
+
/* color selection */
|
142
|
+
bool has_color_select;
|
143
|
+
rgba_list source_select;
|
144
|
+
rgba_list source_ignore;
|
145
|
+
rgba_list dest_select;
|
146
|
+
rgba_list dest_ignore;
|
147
|
+
|
148
|
+
} pen;
|
149
|
+
|
150
|
+
} action_struct;
|
151
|
+
|
152
|
+
|
153
|
+
#endif
|
data/ext/texplay/utils.c
CHANGED
@@ -1,891 +1,896 @@
|
|
1
|
-
/* utils.c */
|
2
|
-
#include <stdio.h>
|
3
|
-
#include <string.h>
|
4
|
-
#include <ctype.h>
|
5
|
-
#include <ruby.h>
|
6
|
-
#include <stdarg.h>
|
7
|
-
#include <assert.h>
|
8
|
-
#include <stdlib.h>
|
9
|
-
#include <math.h>
|
10
|
-
#include "cache.h"
|
11
|
-
#include "texplay.h"
|
12
|
-
#include "utils.h"
|
13
|
-
|
14
|
-
#ifdef __APPLE__
|
15
|
-
#include <
|
16
|
-
#
|
17
|
-
#include <
|
18
|
-
#
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
"movups (%
|
31
|
-
"
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
{
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
VALUE
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
{
|
78
|
-
return TYPE(
|
79
|
-
}
|
80
|
-
|
81
|
-
VALUE
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
return false;
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
}
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
set_array_value(
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
set_array_value(
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
}
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
color
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
cur_color
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
rb_funcall(
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
my_color
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
/*
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
//
|
644
|
-
outcode0
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
//
|
663
|
-
//
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
{
|
671
|
-
x = tx0 + (tx1 - tx0) * (
|
672
|
-
y =
|
673
|
-
}
|
674
|
-
else if (outcodeOut &
|
675
|
-
{
|
676
|
-
|
677
|
-
|
678
|
-
}
|
679
|
-
else
|
680
|
-
{
|
681
|
-
y = ty0 + (ty1 - ty0) * (
|
682
|
-
x =
|
683
|
-
}
|
684
|
-
//
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
if(*
|
721
|
-
|
722
|
-
|
723
|
-
if(*
|
724
|
-
|
725
|
-
|
726
|
-
if(*
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
/*
|
795
|
-
/*
|
796
|
-
/*
|
797
|
-
|
798
|
-
/*
|
799
|
-
/*
|
800
|
-
/*
|
801
|
-
/*
|
802
|
-
|
803
|
-
/*
|
804
|
-
/*
|
805
|
-
/*
|
806
|
-
/*
|
807
|
-
/*
|
808
|
-
/*
|
809
|
-
|
810
|
-
/*
|
811
|
-
/*
|
812
|
-
/*
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
VALUE
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
1
|
+
/* utils.c */
|
2
|
+
#include <stdio.h>
|
3
|
+
#include <string.h>
|
4
|
+
#include <ctype.h>
|
5
|
+
#include <ruby.h>
|
6
|
+
#include <stdarg.h>
|
7
|
+
#include <assert.h>
|
8
|
+
#include <stdlib.h>
|
9
|
+
#include <math.h>
|
10
|
+
#include "cache.h"
|
11
|
+
#include "texplay.h"
|
12
|
+
#include "utils.h"
|
13
|
+
|
14
|
+
#ifdef __APPLE__
|
15
|
+
# include <AvailabilityMacros.h>
|
16
|
+
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
|
17
|
+
# include <GLUT/glut.h>
|
18
|
+
#else
|
19
|
+
# include <GL/glut.h>
|
20
|
+
#endif
|
21
|
+
#else
|
22
|
+
# include <GL/glut.h>
|
23
|
+
#endif
|
24
|
+
|
25
|
+
/*
|
26
|
+
#define MULT_FLOAT4(X, Y) ({ \
|
27
|
+
asm volatile ( \
|
28
|
+
"movups (%0), %%xmm0\n\t" \
|
29
|
+
"mulps (%1), %%xmm0\n\t" \
|
30
|
+
"movups %%xmm0, (%1)" \
|
31
|
+
:: "r" (X), "r" (Y)); })
|
32
|
+
|
33
|
+
#define COPY_FLOAT4(X, Y) ({ \
|
34
|
+
asm volatile ( \
|
35
|
+
"movups (%0), %%xmm0\n\t" \
|
36
|
+
"movups %%xmm0, (%1)" \
|
37
|
+
:: "r" (X), "r" (Y)); })
|
38
|
+
|
39
|
+
*/
|
40
|
+
/* external linkage with static duration */
|
41
|
+
const rgba not_a_color_v = { -1.0, -1.0, -1.0, -1.0 };
|
42
|
+
|
43
|
+
/* utility functions */
|
44
|
+
char*
|
45
|
+
lowercase(char * string)
|
46
|
+
{
|
47
|
+
int i = 0;
|
48
|
+
|
49
|
+
while (string[i]) {
|
50
|
+
string[i] = tolower(string[i]);
|
51
|
+
i++;
|
52
|
+
}
|
53
|
+
|
54
|
+
return string;
|
55
|
+
}
|
56
|
+
|
57
|
+
char*
|
58
|
+
sym2string(VALUE sym)
|
59
|
+
{
|
60
|
+
return rb_id2name(SYM2ID(sym));
|
61
|
+
}
|
62
|
+
|
63
|
+
VALUE
|
64
|
+
string2sym(char * string)
|
65
|
+
{
|
66
|
+
return ID2SYM(rb_intern(string));
|
67
|
+
}
|
68
|
+
|
69
|
+
bool
|
70
|
+
is_a_hash(VALUE try_hash)
|
71
|
+
{
|
72
|
+
return TYPE(try_hash) == T_HASH;
|
73
|
+
}
|
74
|
+
|
75
|
+
bool
|
76
|
+
is_an_array(VALUE try_array)
|
77
|
+
{
|
78
|
+
return TYPE(try_array) == T_ARRAY;
|
79
|
+
}
|
80
|
+
|
81
|
+
bool is_a_num(VALUE try_num)
|
82
|
+
{
|
83
|
+
return TYPE(try_num) == T_FIXNUM || TYPE(try_num) == T_FLOAT;
|
84
|
+
}
|
85
|
+
|
86
|
+
VALUE
|
87
|
+
get_from_hash(VALUE hash, char * sym)
|
88
|
+
{
|
89
|
+
|
90
|
+
if(TYPE(hash) != T_HASH) rb_raise(rb_eArgError, "hash argument expected");
|
91
|
+
|
92
|
+
return rb_hash_aref(hash, string2sym(sym));
|
93
|
+
}
|
94
|
+
|
95
|
+
VALUE
|
96
|
+
set_hash_value(VALUE hash, char * sym, VALUE val)
|
97
|
+
{
|
98
|
+
if(TYPE(hash) != T_HASH) rb_raise(rb_eArgError, "hash argument expected");
|
99
|
+
|
100
|
+
rb_hash_aset(hash, string2sym(sym), val);
|
101
|
+
|
102
|
+
return val;
|
103
|
+
}
|
104
|
+
|
105
|
+
VALUE
|
106
|
+
delete_from_hash(VALUE hash, char * sym)
|
107
|
+
{
|
108
|
+
if(TYPE(hash) != T_HASH) rb_raise(rb_eArgError, "hash argument expected");
|
109
|
+
|
110
|
+
return rb_hash_delete(hash, string2sym(sym));
|
111
|
+
}
|
112
|
+
|
113
|
+
/* returns true if 'hash' is a hash and the value mapped to key 'sym' is
|
114
|
+
equal to 'val' */
|
115
|
+
bool
|
116
|
+
hash_value_is(VALUE hash, char * sym, VALUE val)
|
117
|
+
{
|
118
|
+
if(TYPE(hash) != T_HASH) return false;
|
119
|
+
|
120
|
+
if(get_from_hash(hash, sym) == val)
|
121
|
+
return true;
|
122
|
+
|
123
|
+
return false;
|
124
|
+
}
|
125
|
+
|
126
|
+
bool
|
127
|
+
has_optional_hash_arg(VALUE hash, char * sym)
|
128
|
+
{
|
129
|
+
if(TYPE(hash) != T_HASH) return false;
|
130
|
+
|
131
|
+
if(NIL_P(get_from_hash(hash, sym)))
|
132
|
+
return false;
|
133
|
+
|
134
|
+
/* 'hash' is a hash and the sym exists */
|
135
|
+
return true;
|
136
|
+
}
|
137
|
+
|
138
|
+
VALUE
|
139
|
+
set_array_value(VALUE array, int index, VALUE val)
|
140
|
+
{
|
141
|
+
if(TYPE(array) != T_ARRAY) rb_raise(rb_eArgError, "array argument expected");
|
142
|
+
|
143
|
+
rb_ary_store(array, index, val);
|
144
|
+
|
145
|
+
return val;
|
146
|
+
}
|
147
|
+
|
148
|
+
VALUE
|
149
|
+
get_from_array(VALUE array, int index)
|
150
|
+
{
|
151
|
+
|
152
|
+
if(TYPE(array) != T_ARRAY) rb_raise(rb_eArgError, "array argument expected");
|
153
|
+
|
154
|
+
return rb_ary_entry(array, index);
|
155
|
+
}
|
156
|
+
|
157
|
+
|
158
|
+
VALUE
|
159
|
+
init_image_local(VALUE image)
|
160
|
+
{
|
161
|
+
VALUE image_local;
|
162
|
+
|
163
|
+
if(!is_gosu_image(image))
|
164
|
+
rb_raise(rb_eArgError, "not a valid image");
|
165
|
+
|
166
|
+
/* initialize image_local hash if does not exist */
|
167
|
+
if(!is_an_array(rb_iv_get(image, "__image_local__"))) {
|
168
|
+
image_local = rb_ary_new();
|
169
|
+
rb_iv_set(image, "__image_local__", image_local);
|
170
|
+
}
|
171
|
+
|
172
|
+
image_local = rb_iv_get(image, "__image_local__");
|
173
|
+
|
174
|
+
return image_local;
|
175
|
+
}
|
176
|
+
|
177
|
+
void
|
178
|
+
set_image_local(VALUE image, int name, VALUE val)
|
179
|
+
{
|
180
|
+
VALUE image_local;
|
181
|
+
|
182
|
+
image_local = init_image_local(image);
|
183
|
+
|
184
|
+
set_array_value(image_local, name, val);
|
185
|
+
}
|
186
|
+
|
187
|
+
VALUE
|
188
|
+
get_image_local(VALUE image, int name)
|
189
|
+
{
|
190
|
+
VALUE image_local;
|
191
|
+
VALUE val;
|
192
|
+
|
193
|
+
init_image_local(image);
|
194
|
+
|
195
|
+
/* this var holds all the image local variables in an array */
|
196
|
+
image_local = rb_iv_get(image, "__image_local__");
|
197
|
+
|
198
|
+
/* a particular image_local variable */
|
199
|
+
val = get_from_array(image_local, name);
|
200
|
+
|
201
|
+
/* if the variable exists then return it */
|
202
|
+
if(!NIL_P(val))
|
203
|
+
return val;
|
204
|
+
|
205
|
+
/* otherwise initialize the variable and then return it */
|
206
|
+
else {
|
207
|
+
switch(name) {
|
208
|
+
VALUE init_offset, init_bounds, init_color, init_defaults;
|
209
|
+
case DRAW_OFFSET:
|
210
|
+
init_offset = rb_ary_new2(2);
|
211
|
+
set_array_value(init_offset, 0, INT2FIX(0));
|
212
|
+
set_array_value(init_offset, 1, INT2FIX(0));
|
213
|
+
|
214
|
+
set_array_value(image_local, DRAW_OFFSET, init_offset);
|
215
|
+
|
216
|
+
return init_offset;
|
217
|
+
break;
|
218
|
+
case LAZY_BOUNDS:
|
219
|
+
init_bounds = rb_ary_new2(4);
|
220
|
+
set_array_value(init_bounds, 0, INT2FIX(XMAX_OOB));
|
221
|
+
set_array_value(init_bounds, 1, INT2FIX(YMAX_OOB));
|
222
|
+
set_array_value(init_bounds, 2, INT2FIX(XMIN_OOB));
|
223
|
+
set_array_value(init_bounds, 3, INT2FIX(YMIN_OOB));
|
224
|
+
|
225
|
+
set_array_value(image_local, LAZY_BOUNDS, init_bounds);
|
226
|
+
|
227
|
+
return init_bounds;
|
228
|
+
break;
|
229
|
+
case IMAGE_COLOR:
|
230
|
+
init_color = rb_ary_new2(4);
|
231
|
+
set_array_value(init_color, 0, rb_float_new(1.0));
|
232
|
+
set_array_value(init_color, 1, rb_float_new(1.0));
|
233
|
+
set_array_value(init_color, 2, rb_float_new(1.0));
|
234
|
+
set_array_value(init_color, 3, rb_float_new(1.0));
|
235
|
+
|
236
|
+
set_array_value(image_local, IMAGE_COLOR, init_color);
|
237
|
+
|
238
|
+
return init_color;
|
239
|
+
break;
|
240
|
+
case USER_DEFAULTS:
|
241
|
+
init_defaults = rb_hash_new();
|
242
|
+
|
243
|
+
set_array_value(image_local, USER_DEFAULTS, init_defaults);
|
244
|
+
|
245
|
+
return init_defaults;
|
246
|
+
break;
|
247
|
+
default:
|
248
|
+
rb_raise(rb_eArgError, "unrecognized image_local variable number. got %d", name);
|
249
|
+
}
|
250
|
+
}
|
251
|
+
|
252
|
+
/* never reached */
|
253
|
+
return Qnil;
|
254
|
+
}
|
255
|
+
|
256
|
+
rgba
|
257
|
+
convert_image_local_color_to_rgba(VALUE image)
|
258
|
+
{
|
259
|
+
rgba color;
|
260
|
+
VALUE image_local_color = get_image_local(image, IMAGE_COLOR);
|
261
|
+
|
262
|
+
color.red = NUM2DBL(get_from_array(image_local_color, red));
|
263
|
+
color.green = NUM2DBL(get_from_array(image_local_color, green));
|
264
|
+
color.blue = NUM2DBL(get_from_array(image_local_color, blue));
|
265
|
+
color.alpha = NUM2DBL(get_from_array(image_local_color, alpha));
|
266
|
+
|
267
|
+
return color;
|
268
|
+
}
|
269
|
+
|
270
|
+
VALUE
|
271
|
+
save_rgba_to_image_local_color(VALUE image, rgba color)
|
272
|
+
{
|
273
|
+
/* abbreviation for image_local_color */
|
274
|
+
VALUE ilc = get_image_local(image, IMAGE_COLOR);
|
275
|
+
|
276
|
+
set_array_value(ilc, 0, rb_float_new(color.red));
|
277
|
+
set_array_value(ilc, 1, rb_float_new(color.green));
|
278
|
+
set_array_value(ilc, 2, rb_float_new(color.blue));
|
279
|
+
set_array_value(ilc, 3, rb_float_new(color.alpha));
|
280
|
+
|
281
|
+
return ilc;
|
282
|
+
}
|
283
|
+
|
284
|
+
bool
|
285
|
+
not_a_color(rgba color1)
|
286
|
+
{
|
287
|
+
return color1.red == -1 || color1.green == -1 ||
|
288
|
+
color1.blue == -1 || color1.alpha == -1;
|
289
|
+
}
|
290
|
+
|
291
|
+
bool
|
292
|
+
is_a_color(rgba color1)
|
293
|
+
{
|
294
|
+
return !not_a_color(color1);
|
295
|
+
}
|
296
|
+
|
297
|
+
bool
|
298
|
+
is_rb_raw_color(VALUE cval)
|
299
|
+
{
|
300
|
+
return TYPE(cval) == T_ARRAY &&
|
301
|
+
is_a_num(get_from_array(cval, 0)) &&
|
302
|
+
is_a_num(get_from_array(cval, 1)) &&
|
303
|
+
is_a_num(get_from_array(cval, 2)) &&
|
304
|
+
is_a_num(get_from_array(cval, 3));
|
305
|
+
}
|
306
|
+
|
307
|
+
bool
|
308
|
+
not_rb_raw_color(VALUE cval)
|
309
|
+
{
|
310
|
+
return TYPE(cval) != T_ARRAY ||
|
311
|
+
!is_a_num(get_from_array(cval, 0));
|
312
|
+
}
|
313
|
+
|
314
|
+
/** cmp_color related functions **/
|
315
|
+
static bool
|
316
|
+
is_transparent_color(rgba color1)
|
317
|
+
{
|
318
|
+
return color1.red == -666 && color1.green == -666 && color1.blue == -666 &&
|
319
|
+
color1.alpha == -666;
|
320
|
+
}
|
321
|
+
|
322
|
+
static bool
|
323
|
+
special_cmp_color(rgba color1, rgba color2)
|
324
|
+
{
|
325
|
+
if (is_transparent_color(color1))
|
326
|
+
return color2.alpha == 0;
|
327
|
+
else if (is_transparent_color(color2))
|
328
|
+
return color1.alpha == 0;
|
329
|
+
else
|
330
|
+
return false;
|
331
|
+
}
|
332
|
+
|
333
|
+
static bool
|
334
|
+
special_cmp_color_with_tolerance(rgba color1, rgba color2, float tolerance)
|
335
|
+
{
|
336
|
+
if (is_transparent_color(color1))
|
337
|
+
return (color2.alpha) <= tolerance;
|
338
|
+
else if (is_transparent_color(color2))
|
339
|
+
return color1.alpha <= tolerance;
|
340
|
+
else
|
341
|
+
return false;
|
342
|
+
}
|
343
|
+
|
344
|
+
|
345
|
+
static float
|
346
|
+
color_distance_squared(rgba c1, rgba c2)
|
347
|
+
{
|
348
|
+
return (c1.red - c2.red) * (c1.red - c2.red) +
|
349
|
+
(c1.green - c2.green) * (c1.green - c2.green) +
|
350
|
+
(c1.blue - c2.blue) * (c1.blue - c2.blue) +
|
351
|
+
(c1.alpha - c2.alpha) * (c1.alpha - c2.alpha);
|
352
|
+
}
|
353
|
+
|
354
|
+
|
355
|
+
bool
|
356
|
+
cmp_color_with_tolerance(rgba color1, rgba color2, float tolerance)
|
357
|
+
{
|
358
|
+
if (color1.red < 0 || color2.red < 0)
|
359
|
+
return special_cmp_color_with_tolerance(color1, color2, tolerance);
|
360
|
+
|
361
|
+
return color_distance_squared(color1, color2) <= (tolerance * tolerance);
|
362
|
+
}
|
363
|
+
|
364
|
+
bool
|
365
|
+
cmp_color(rgba color1, rgba color2)
|
366
|
+
{
|
367
|
+
if (color1.red < 0 || color2.red < 0)
|
368
|
+
return special_cmp_color(color1, color2);
|
369
|
+
|
370
|
+
return (color1.red == color2.red) && (color1.green == color2.green) && (color1.blue == color2.blue)
|
371
|
+
&& (color1.alpha == color2.alpha);
|
372
|
+
}
|
373
|
+
|
374
|
+
|
375
|
+
/*** these functions are UNSAFE ***/
|
376
|
+
void
|
377
|
+
color_copy(float * source, float * dest)
|
378
|
+
{
|
379
|
+
//COPY_FLOAT4(source, dest);
|
380
|
+
memcpy(dest, source, 4 * sizeof(float));
|
381
|
+
}
|
382
|
+
|
383
|
+
void
|
384
|
+
zero_color(float * tex)
|
385
|
+
{
|
386
|
+
memset(tex, 0, 4 * sizeof(float));
|
387
|
+
}
|
388
|
+
/*** ***/
|
389
|
+
|
390
|
+
rgba
|
391
|
+
find_color_from_string(char * try_color)
|
392
|
+
{
|
393
|
+
rgba cur_color;
|
394
|
+
|
395
|
+
if(!strcmp("red", try_color)) {
|
396
|
+
cur_color.red = 1.0; cur_color.green = 0.0; cur_color.blue = 0.0; cur_color.alpha = 1.0;
|
397
|
+
}
|
398
|
+
else if(!strcmp("green", try_color)) {
|
399
|
+
cur_color.red = 0.0; cur_color.green = 1.0; cur_color.blue = 0.0; cur_color.alpha = 1.0;
|
400
|
+
}
|
401
|
+
else if(!strcmp("blue", try_color)) {
|
402
|
+
cur_color.red = 0.0; cur_color.green = 0.0; cur_color.blue = 1.0; cur_color.alpha = 1.0;
|
403
|
+
}
|
404
|
+
else if(!strcmp("black", try_color)) {
|
405
|
+
cur_color.red = 0.0; cur_color.green = 0.0; cur_color.blue = 0.0; cur_color.alpha = 1.0;
|
406
|
+
}
|
407
|
+
else if(!strcmp("white", try_color)) {
|
408
|
+
cur_color.red = 1.0; cur_color.green = 1.0; cur_color.blue = 1.0; cur_color.alpha = 1.0;
|
409
|
+
}
|
410
|
+
else if(!strcmp("purple", try_color)) {
|
411
|
+
cur_color.red = 1.0; cur_color.green = 0.0; cur_color.blue = 1.0; cur_color.alpha = 1.0;
|
412
|
+
}
|
413
|
+
else if(!strcmp("yellow", try_color)) {
|
414
|
+
cur_color.red = 1.0; cur_color.green = 1.0; cur_color.blue = 0.0; cur_color.alpha = 1.0;
|
415
|
+
}
|
416
|
+
else if(!strcmp("cyan", try_color)) {
|
417
|
+
cur_color.red = 0.0; cur_color.green = 1.0; cur_color.blue = 1.0; cur_color.alpha = 1.0;
|
418
|
+
}
|
419
|
+
else if(!strcmp("orange", try_color)) {
|
420
|
+
cur_color.red = 1.0; cur_color.green = 0.5; cur_color.blue = 0.0; cur_color.alpha = 1.0;
|
421
|
+
}
|
422
|
+
else if(!strcmp("brown", try_color)) {
|
423
|
+
cur_color.red = 0.39; cur_color.green = 0.26; cur_color.blue = 0.13; cur_color.alpha = 1.0;
|
424
|
+
}
|
425
|
+
else if(!strcmp("turquoise", try_color)) {
|
426
|
+
cur_color.red = 0.1; cur_color.green = 0.6; cur_color.blue = 0.8; cur_color.alpha = 1.0;
|
427
|
+
}
|
428
|
+
else if(!strcmp("tyrian", try_color)) {
|
429
|
+
cur_color.red = 0.4; cur_color.green = 0.007; cur_color.blue = 0.235; cur_color.alpha = 1.0;
|
430
|
+
}
|
431
|
+
else if(!strcmp("alpha", try_color)) {
|
432
|
+
cur_color.red = 0.0; cur_color.green = 0.0; cur_color.blue = 0.0; cur_color.alpha = 0.0;
|
433
|
+
}
|
434
|
+
else if(!strcmp("transparent", try_color)) {
|
435
|
+
cur_color.red = -666; cur_color.green = -666; cur_color.blue = -666; cur_color.alpha = -666;
|
436
|
+
}
|
437
|
+
else if(!strcmp("none", try_color)) {
|
438
|
+
cur_color = not_a_color_v;
|
439
|
+
}
|
440
|
+
else if(!strcmp("random", try_color) || !strcmp("rand", try_color)) {
|
441
|
+
cur_color.red = rand() / (float)RAND_MAX;
|
442
|
+
cur_color.green = rand() / (float)RAND_MAX;
|
443
|
+
cur_color.blue = rand() / (float)RAND_MAX;
|
444
|
+
cur_color.alpha = 1.0;
|
445
|
+
}
|
446
|
+
|
447
|
+
else
|
448
|
+
rb_raise(rb_eArgError, "invalid colour specified (no color matches the symbol: %s)\n", try_color);
|
449
|
+
|
450
|
+
return cur_color;
|
451
|
+
}
|
452
|
+
|
453
|
+
rgba
|
454
|
+
convert_gosu_to_rgba_color(VALUE gcolor)
|
455
|
+
{
|
456
|
+
|
457
|
+
return (rgba) {
|
458
|
+
FIX2INT(rb_funcall(gcolor, rb_intern("red"), 0)) / 255.0,
|
459
|
+
FIX2INT(rb_funcall(gcolor, rb_intern("green"), 0)) / 255.0,
|
460
|
+
FIX2INT(rb_funcall(gcolor, rb_intern("blue"), 0)) / 255.0,
|
461
|
+
FIX2INT(rb_funcall(gcolor, rb_intern("alpha"), 0)) / 255.0
|
462
|
+
};
|
463
|
+
}
|
464
|
+
|
465
|
+
|
466
|
+
/* convert C color to Ruby color */
|
467
|
+
VALUE
|
468
|
+
convert_rgba_to_rb_color(rgba * pix)
|
469
|
+
{
|
470
|
+
if (not_a_color(*pix)) return Qnil;
|
471
|
+
|
472
|
+
/* create a new ruby array to store the pixel data */
|
473
|
+
VALUE pix_array = rb_ary_new2(4);
|
474
|
+
|
475
|
+
/* store the pixel data */
|
476
|
+
rb_ary_store(pix_array, red, rb_float_new(pix->red));
|
477
|
+
rb_ary_store(pix_array, green, rb_float_new(pix->green));
|
478
|
+
rb_ary_store(pix_array, blue, rb_float_new(pix->blue));
|
479
|
+
rb_ary_store(pix_array, alpha, rb_float_new(pix->alpha));
|
480
|
+
|
481
|
+
return pix_array;
|
482
|
+
}
|
483
|
+
|
484
|
+
/* convert C color to gosu color */
|
485
|
+
VALUE
|
486
|
+
convert_rgba_to_gosu_color(rgba * pix)
|
487
|
+
{
|
488
|
+
if (not_a_color(*pix)) return Qnil;
|
489
|
+
|
490
|
+
VALUE gosu_color = rb_funcall(gosu_color_class(), rb_intern("new"), 0);
|
491
|
+
|
492
|
+
rb_funcall(gosu_color, rb_intern("red="), 1, INT2FIX(pix->red * 255));
|
493
|
+
rb_funcall(gosu_color, rb_intern("green="), 1, INT2FIX(pix->green * 255));
|
494
|
+
rb_funcall(gosu_color, rb_intern("blue="), 1, INT2FIX(pix->blue * 255));
|
495
|
+
rb_funcall(gosu_color, rb_intern("alpha="), 1, INT2FIX(pix->alpha * 255));
|
496
|
+
|
497
|
+
return gosu_color;
|
498
|
+
}
|
499
|
+
|
500
|
+
VALUE
|
501
|
+
gosu_color_class()
|
502
|
+
{
|
503
|
+
static VALUE gcolor_class = 0;
|
504
|
+
|
505
|
+
if (gcolor_class == 0) {
|
506
|
+
VALUE gosu_class = rb_const_get(rb_cObject, rb_intern("Gosu"));
|
507
|
+
gcolor_class = rb_const_get(gosu_class, rb_intern("Color"));
|
508
|
+
}
|
509
|
+
|
510
|
+
return gcolor_class;
|
511
|
+
}
|
512
|
+
|
513
|
+
/* convert Ruby color to C color */
|
514
|
+
rgba
|
515
|
+
convert_rb_color_to_rgba(VALUE cval)
|
516
|
+
{
|
517
|
+
rgba my_color;
|
518
|
+
|
519
|
+
if (is_gosu_color(cval)) return convert_gosu_to_rgba_color(cval);
|
520
|
+
|
521
|
+
/* current color for actions */
|
522
|
+
switch(TYPE(cval)) {
|
523
|
+
char * try_color;
|
524
|
+
case T_SYMBOL:
|
525
|
+
try_color = lowercase(sym2string(cval));
|
526
|
+
|
527
|
+
my_color = find_color_from_string(try_color);
|
528
|
+
|
529
|
+
break;
|
530
|
+
case T_ARRAY:
|
531
|
+
my_color.red = NUM2DBL(rb_ary_entry(cval, red));
|
532
|
+
my_color.green = NUM2DBL(rb_ary_entry(cval, green));
|
533
|
+
my_color.blue = NUM2DBL(rb_ary_entry(cval, blue));
|
534
|
+
|
535
|
+
if(NUM2INT(rb_funcall(cval, rb_intern("length"), 0)) > 3)
|
536
|
+
my_color.alpha = NUM2DBL(rb_ary_entry(cval, alpha));
|
537
|
+
else
|
538
|
+
my_color.alpha = 1;
|
539
|
+
|
540
|
+
break;
|
541
|
+
|
542
|
+
/* hex literals */
|
543
|
+
case T_FIXNUM:
|
544
|
+
case T_BIGNUM:
|
545
|
+
return convert_gosu_to_rgba_color(rb_funcall(gosu_color_class(),
|
546
|
+
rb_intern("new"), 1, cval));
|
547
|
+
break;
|
548
|
+
|
549
|
+
default:
|
550
|
+
rb_raise(rb_eArgError, "unsupported argument type for color. Got type 0x%x\n", TYPE(cval) );
|
551
|
+
}
|
552
|
+
|
553
|
+
/* a valid color */
|
554
|
+
if(is_a_color(my_color))
|
555
|
+
return my_color;
|
556
|
+
|
557
|
+
/* special condition for when color is taken from outside range of bitmap. Color is just ignored */
|
558
|
+
else if(not_a_color(my_color))
|
559
|
+
return not_a_color_v;
|
560
|
+
|
561
|
+
/* anything else should fail */
|
562
|
+
else
|
563
|
+
rb_raise(rb_eArgError, "invalid colour specified (negative value given)\n");
|
564
|
+
}
|
565
|
+
|
566
|
+
/* error checking functions */
|
567
|
+
void
|
568
|
+
check_mask(VALUE mask)
|
569
|
+
{
|
570
|
+
char * try_mask;
|
571
|
+
|
572
|
+
if(TYPE(mask) != T_ARRAY && TYPE(mask) != T_SYMBOL)
|
573
|
+
rb_raise(rb_eArgError, "array or symbol parameter required");
|
574
|
+
|
575
|
+
/* is it a valid mask symbol? */
|
576
|
+
if(TYPE(mask) == T_SYMBOL) {
|
577
|
+
try_mask = lowercase(sym2string(mask));
|
578
|
+
if(*try_mask == '_') try_mask++;
|
579
|
+
if(not_a_color(find_color_from_string(try_mask))) {
|
580
|
+
rb_raise(rb_eArgError, "unrecognized mask symbol: %s\n", sym2string(mask));
|
581
|
+
}
|
582
|
+
}
|
583
|
+
}
|
584
|
+
|
585
|
+
void
|
586
|
+
check_image(VALUE image)
|
587
|
+
{
|
588
|
+
if(!rb_respond_to(image, rb_intern("gl_tex_info")))
|
589
|
+
rb_raise(rb_eRuntimeError,"must specify a valid source image");
|
590
|
+
}
|
591
|
+
|
592
|
+
bool
|
593
|
+
is_gosu_image(VALUE try_image)
|
594
|
+
{
|
595
|
+
if(rb_respond_to(try_image, rb_intern("gl_tex_info")))
|
596
|
+
return true;
|
597
|
+
|
598
|
+
return false;
|
599
|
+
}
|
600
|
+
|
601
|
+
bool
|
602
|
+
is_gosu_color(VALUE try_color)
|
603
|
+
{
|
604
|
+
if(rb_respond_to(try_color, rb_intern("red")))
|
605
|
+
return true;
|
606
|
+
|
607
|
+
return false;
|
608
|
+
}
|
609
|
+
|
610
|
+
|
611
|
+
|
612
|
+
/** cohen-sutherland line clipper **/
|
613
|
+
#define outcode int
|
614
|
+
const int RIGHT = 8; //1000
|
615
|
+
const int TOP = 4; //0100
|
616
|
+
const int LEFT = 2; //0010
|
617
|
+
const int BOTTOM = 1; //0001
|
618
|
+
|
619
|
+
//Compute the bit code for a point (x, y) using the clip rectangle
|
620
|
+
//bounded diagonally by (xmin, ymin), and (xmax, ymax)
|
621
|
+
static outcode
|
622
|
+
ComputeOutCode (int x, int y, int xmin, int ymin, int xmax, int ymax)
|
623
|
+
{
|
624
|
+
outcode code = 0;
|
625
|
+
if (y > ymax) //above the clip window
|
626
|
+
code |= TOP;
|
627
|
+
else if (y < ymin) //below the clip window
|
628
|
+
code |= BOTTOM;
|
629
|
+
if (x > xmax) //to the right of clip window
|
630
|
+
code |= RIGHT;
|
631
|
+
else if (x < xmin) //to the left of clip window
|
632
|
+
code |= LEFT;
|
633
|
+
return code;
|
634
|
+
}
|
635
|
+
|
636
|
+
/** Cohen-Sutherland clipping algorithm clips a line from
|
637
|
+
P0 = (x0, y0) to P1 = (x1, y1) against a rectangle with
|
638
|
+
diagonal from (xmin, ymin) to (xmax, ymax). **/
|
639
|
+
void
|
640
|
+
cohen_sutherland_clip (int * x0, int * y0,int * x1, int * y1, int xmin, int ymin,
|
641
|
+
int xmax, int ymax)
|
642
|
+
{
|
643
|
+
//Outcodes for P0, P1, and whatever point lies outside the clip rectangle
|
644
|
+
outcode outcode0, outcode1, outcodeOut;
|
645
|
+
bool accept = false, done = false;
|
646
|
+
int tx0 = *x0, ty0 = *y0, tx1 = *x1, ty1 = *y1;
|
647
|
+
|
648
|
+
//compute outcodes
|
649
|
+
outcode0 = ComputeOutCode (tx0, ty0, xmin, ymin, xmax, ymax);
|
650
|
+
outcode1 = ComputeOutCode (tx1, ty1, xmin, ymin, xmax, ymax);
|
651
|
+
|
652
|
+
do{
|
653
|
+
if (!(outcode0 | outcode1)) //logical or is 0. Trivially accept and get out of loop
|
654
|
+
{
|
655
|
+
accept = true;
|
656
|
+
done = true;
|
657
|
+
}
|
658
|
+
else if (outcode0 & outcode1) //logical and is not 0. Trivially reject and get out of loop
|
659
|
+
done = true;
|
660
|
+
else
|
661
|
+
{
|
662
|
+
//failed both tests, so calculate the line segment to clip
|
663
|
+
//from an outside point to an intersection with clip edge
|
664
|
+
double x, y;
|
665
|
+
//At least one endpoint is outside the clip rectangle; pick it.
|
666
|
+
outcodeOut = outcode0? outcode0: outcode1;
|
667
|
+
//Now find the intersection point;
|
668
|
+
//use formulas y = y0 + slope * (x - x0), x = x0 + (1/slope)* (y - y0)
|
669
|
+
if (outcodeOut & TOP) //point is above the clip rectangle
|
670
|
+
{
|
671
|
+
x = tx0 + (tx1 - tx0) * (ymax - ty0)/(ty1 - ty0);
|
672
|
+
y = ymax;
|
673
|
+
}
|
674
|
+
else if (outcodeOut & BOTTOM) //point is below the clip rectangle
|
675
|
+
{
|
676
|
+
x = tx0 + (tx1 - tx0) * (ymin - ty0)/(ty1 - ty0);
|
677
|
+
y = ymin;
|
678
|
+
}
|
679
|
+
else if (outcodeOut & RIGHT) //point is to the right of clip rectangle
|
680
|
+
{
|
681
|
+
y = ty0 + (ty1 - ty0) * (xmax - tx0)/(tx1 - tx0);
|
682
|
+
x = xmax;
|
683
|
+
}
|
684
|
+
else //point is to the left of clip rectangle
|
685
|
+
{
|
686
|
+
y = ty0 + (ty1 - ty0) * (xmin - tx0)/(tx1 - tx0);
|
687
|
+
x = xmin;
|
688
|
+
}
|
689
|
+
//Now we move outside point to intersection point to clip
|
690
|
+
//and get ready for next pass.
|
691
|
+
if (outcodeOut == outcode0)
|
692
|
+
{
|
693
|
+
tx0 = x;
|
694
|
+
ty0 = y;
|
695
|
+
outcode0 = ComputeOutCode (tx0, ty0, xmin, ymin, xmax, ymax);
|
696
|
+
}
|
697
|
+
else
|
698
|
+
{
|
699
|
+
tx1 = x;
|
700
|
+
ty1 = y;
|
701
|
+
outcode1 = ComputeOutCode (tx1, ty1, xmin, ymin, xmax, ymax);
|
702
|
+
}
|
703
|
+
}
|
704
|
+
}while (!done);
|
705
|
+
|
706
|
+
if (accept)
|
707
|
+
{
|
708
|
+
*x0 = tx0; *x1 = tx1;
|
709
|
+
*y0 = ty0; *y1 = ty1;
|
710
|
+
}
|
711
|
+
|
712
|
+
}
|
713
|
+
/** end of cohen-sutherland line clipper **/
|
714
|
+
|
715
|
+
|
716
|
+
void
|
717
|
+
constrain_boundaries(int * x0, int * y0, int * x1, int * y1, int width, int height)
|
718
|
+
{
|
719
|
+
if(*y0 < 0) *y0 = 0;
|
720
|
+
if(*y1 < 0) *y1 = 0;
|
721
|
+
|
722
|
+
if(*x0 < 0) *x0 = 0;
|
723
|
+
if(*x1 < 0) *x1 = 0;
|
724
|
+
|
725
|
+
if(*x0 > (width - 1)) *x0 = width - 1;
|
726
|
+
if(*x1 > (width - 1)) *x1 = width - 1;
|
727
|
+
|
728
|
+
if(*y0 > (height - 1)) *y0 = height - 1;
|
729
|
+
if(*y1 > (height - 1)) *y1 = height - 1;
|
730
|
+
|
731
|
+
if(*y0 > *y1) { SWAP(*y0, *y1); }
|
732
|
+
if(*x0 > *x1) { SWAP(*x0, *x1); }
|
733
|
+
}
|
734
|
+
|
735
|
+
|
736
|
+
/* returns true if point (x, y) is within bounds designated by rect (x0, y0)-(x1, y1)
|
737
|
+
and inner thickness: 'inner'
|
738
|
+
*/
|
739
|
+
bool
|
740
|
+
bound_by_rect_and_inner(int x, int y, int x0, int y0, int x1, int y1, int inner)
|
741
|
+
{
|
742
|
+
|
743
|
+
return ((x >= x0) && (x <= x1) && (y >= y0) && (y <= y1)) &&
|
744
|
+
!((x >= x0 + inner) && (x <= x1 - inner) && (y >= y0 + inner) && (y <= y1 - inner));
|
745
|
+
}
|
746
|
+
|
747
|
+
/* same as above but excluding inner rectangle */
|
748
|
+
bool
|
749
|
+
bound_by_rect(int x, int y, int x0, int y0, int x1, int y1)
|
750
|
+
{
|
751
|
+
return bound_by_rect_and_inner(x, y, x0, y0, x1, y1, OOB_VAL);
|
752
|
+
}
|
753
|
+
|
754
|
+
/* calculate the array offset for a given pixel in action context */
|
755
|
+
int
|
756
|
+
calc_pixel_offset_for_action(action_struct * cur, texture_info * tex, int x, int y)
|
757
|
+
{
|
758
|
+
int offset = calc_pixel_offset(tex, x + cur->xmin, y + cur->ymin);
|
759
|
+
|
760
|
+
return offset;
|
761
|
+
}
|
762
|
+
|
763
|
+
/* calculate the array offset for a given pixel */
|
764
|
+
int
|
765
|
+
calc_pixel_offset(texture_info * tex, int x, int y)
|
766
|
+
{
|
767
|
+
int offset = 4 * (tex->firstpixel + x + tex->yincr * y);
|
768
|
+
|
769
|
+
return offset;
|
770
|
+
}
|
771
|
+
|
772
|
+
/* NEWEST version that solves segfault on linux, back
|
773
|
+
in action due to availability of MAX_TEXTURE_SIZE constant
|
774
|
+
in ruby 1.8 */
|
775
|
+
unsigned
|
776
|
+
max_quad_size(void)
|
777
|
+
{
|
778
|
+
#if 1
|
779
|
+
return 1024;
|
780
|
+
#endif
|
781
|
+
|
782
|
+
static unsigned size = 0;
|
783
|
+
|
784
|
+
if (size == 0) {
|
785
|
+
VALUE gosu = rb_const_get(rb_cObject, rb_intern("Gosu"));
|
786
|
+
VALUE rb_size = rb_const_get(gosu, rb_intern("MAX_TEXTURE_SIZE"));
|
787
|
+
|
788
|
+
size = FIX2INT(rb_size);
|
789
|
+
}
|
790
|
+
|
791
|
+
return size;
|
792
|
+
}
|
793
|
+
|
794
|
+
/* old version for quick update, OUT OF ACTIONN */
|
795
|
+
/* unsigned */
|
796
|
+
/* max_quad_size(void) */
|
797
|
+
/* { */
|
798
|
+
/* #ifdef __APPLE__ */
|
799
|
+
/* return 1024; */
|
800
|
+
/* #else */
|
801
|
+
/* static unsigned MIN_SIZE = 256, MAX_SIZE = 1024; */
|
802
|
+
|
803
|
+
/* static unsigned size = 0; */
|
804
|
+
/* if (size == 0) */
|
805
|
+
/* { */
|
806
|
+
/* GLint width = 1; */
|
807
|
+
/* size = MIN_SIZE / 2; */
|
808
|
+
/* do { */
|
809
|
+
/* size *= 2; */
|
810
|
+
/* glTexImage2D(GL_PROXY_TEXTURE_2D, 0, 4, size * 2, size * 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); */
|
811
|
+
/* glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); */
|
812
|
+
/* } while (width != 0 && size < MAX_SIZE); */
|
813
|
+
/* } */
|
814
|
+
|
815
|
+
/* return size; */
|
816
|
+
/* #endif */
|
817
|
+
/* } */
|
818
|
+
|
819
|
+
/* point format utilities */
|
820
|
+
bool
|
821
|
+
is_a_point(VALUE try_point)
|
822
|
+
{
|
823
|
+
/* if it responds to 'x' it's near enough (technically must respond to x AND y) */
|
824
|
+
/* added the is_a_num() check due to WEIRD bug where FIXNUMS were responding to the 'x' method (wtf?) but returning nil when invoked */
|
825
|
+
if(rb_respond_to(try_point, rb_intern("x")) && !is_a_num(try_point))
|
826
|
+
return true;
|
827
|
+
|
828
|
+
return false;
|
829
|
+
}
|
830
|
+
|
831
|
+
VALUE
|
832
|
+
point_x(VALUE point)
|
833
|
+
{
|
834
|
+
return rb_funcall(point, rb_intern("x"), 0);
|
835
|
+
}
|
836
|
+
|
837
|
+
VALUE
|
838
|
+
point_y(VALUE point)
|
839
|
+
{
|
840
|
+
return rb_funcall(point, rb_intern("y"), 0);
|
841
|
+
}
|
842
|
+
|
843
|
+
/* mathematical utils, used mainly by bezier curves */
|
844
|
+
double
|
845
|
+
power(float base, int exp)
|
846
|
+
{
|
847
|
+
float ans = 1.0;
|
848
|
+
if(base == 0.0) {
|
849
|
+
if(exp == 0)
|
850
|
+
return 1;
|
851
|
+
else
|
852
|
+
return 0;
|
853
|
+
}
|
854
|
+
else if(exp == 0) return 1;
|
855
|
+
else {
|
856
|
+
for(int k = exp; k >= 1; k--) {
|
857
|
+
ans = ans * base;
|
858
|
+
}
|
859
|
+
return ans;
|
860
|
+
}
|
861
|
+
}
|
862
|
+
|
863
|
+
unsigned
|
864
|
+
fact(int n)
|
865
|
+
{
|
866
|
+
if (n == 0 || n == 1) return 1;
|
867
|
+
else
|
868
|
+
return (n * fact(n - 1));
|
869
|
+
}
|
870
|
+
|
871
|
+
unsigned
|
872
|
+
comb(int n, int r)
|
873
|
+
{
|
874
|
+
/* nCr is symmetrical about n / 2 */
|
875
|
+
if(r > (n / 2))
|
876
|
+
r = n - r;
|
877
|
+
|
878
|
+
return perm(n, r) / fact(r);
|
879
|
+
}
|
880
|
+
|
881
|
+
unsigned
|
882
|
+
perm(int n, int r)
|
883
|
+
{
|
884
|
+
int val = 1;
|
885
|
+
for(int i = n; i > (n - r); i--)
|
886
|
+
val *= i;
|
887
|
+
|
888
|
+
return val;
|
889
|
+
}
|
890
|
+
|
891
|
+
double
|
892
|
+
bernstein(int n, int k, float u)
|
893
|
+
{
|
894
|
+
double temp = comb(n, k) * pow(u, k) * pow(1 - u, n - k);
|
895
|
+
return temp;
|
896
|
+
}
|