texplay 0.3.5 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/CHANGELOG +222 -222
  2. data/README.markdown +43 -43
  3. data/Rakefile +3 -99
  4. data/examples/common.rb +18 -18
  5. data/examples/example_alpha_blend.rb +29 -29
  6. data/examples/example_bezier.rb +41 -41
  7. data/examples/example_blank.rb +37 -37
  8. data/examples/example_cache.rb +21 -21
  9. data/examples/example_color_control.rb +69 -69
  10. data/examples/example_color_transform.rb +62 -62
  11. data/examples/example_color_transform_circle.rb +34 -34
  12. data/examples/example_darken.rb +24 -24
  13. data/examples/example_dup.rb +73 -73
  14. data/examples/example_each.rb +39 -39
  15. data/examples/example_effect.rb +34 -34
  16. data/examples/example_fill.rb +43 -43
  17. data/examples/example_fill_old.rb +48 -48
  18. data/examples/example_fluent.rb +29 -29
  19. data/examples/example_font.rb +31 -31
  20. data/examples/example_hash_arguments.rb +46 -46
  21. data/examples/example_ippa.rb +23 -23
  22. data/examples/example_light.rb +75 -75
  23. data/examples/example_light_multiply.rb +18 -18
  24. data/examples/example_lsystem.rb +61 -61
  25. data/examples/example_melt.rb +25 -25
  26. data/examples/example_meyet.rb +62 -62
  27. data/examples/example_polyline.rb +42 -42
  28. data/examples/example_scale.rb +27 -27
  29. data/examples/example_select.rb +36 -36
  30. data/examples/example_select2.rb +25 -25
  31. data/examples/example_simple.rb +46 -46
  32. data/examples/example_splice.rb +26 -26
  33. data/examples/example_sync.rb +59 -59
  34. data/examples/example_tiles.rb +41 -41
  35. data/examples/example_trace.rb +22 -22
  36. data/examples/example_transparent.rb +28 -28
  37. data/examples/example_transparent2.rb +24 -24
  38. data/examples/example_transparent3.rb +20 -20
  39. data/examples/example_turtle.rb +39 -39
  40. data/examples/example_weird.rb +22 -22
  41. data/examples/example_window_render_to_image.rb +41 -41
  42. data/examples/example_window_to_blob.rb +35 -35
  43. data/examples/media/maria.png +0 -0
  44. data/examples/media/rose.bmp +0 -0
  45. data/ext/texplay/actions.c +1006 -1006
  46. data/ext/texplay/actions.h +60 -60
  47. data/ext/texplay/bindings.c +1125 -1186
  48. data/ext/texplay/bindings.h +46 -46
  49. data/ext/texplay/cache.c +118 -118
  50. data/ext/texplay/cache.h +24 -24
  51. data/ext/texplay/compat.h +27 -27
  52. data/ext/texplay/extconf.rb +28 -28
  53. data/ext/texplay/graphics_utils.c +1313 -1313
  54. data/ext/texplay/graphics_utils.h +22 -22
  55. data/ext/texplay/texplay.c +201 -216
  56. data/ext/texplay/texplay.h +153 -153
  57. data/ext/texplay/utils.c +891 -891
  58. data/ext/texplay/utils.h +153 -153
  59. data/lib/texplay-contrib.rb +147 -164
  60. data/lib/texplay.rb +341 -356
  61. data/lib/texplay/alone.rb +20 -20
  62. data/lib/texplay/c_function_docs.rb +178 -190
  63. data/lib/texplay/live.rb +84 -84
  64. data/lib/texplay/version.rb +3 -3
  65. data/live/live.rb +85 -85
  66. data/test/image_spec.rb +45 -45
  67. data/test/texplay_spec.rb +144 -141
  68. metadata +54 -42
  69. data/examples/example_gen_eval.rb +0 -32
  70. data/ext/texplay/gen_eval.c +0 -211
  71. data/ext/texplay/gen_eval.h +0 -20
  72. data/ext/texplay/object2module.c +0 -171
  73. data/ext/texplay/object2module.h +0 -11
data/ext/texplay/utils.h CHANGED
@@ -1,153 +1,153 @@
1
- #ifndef GUARD_UTILS_H
2
- #define GUARD_UTILS_H
3
-
4
-
5
- /* for use with get_image_local, and set_image_local */
6
- #define DRAW_OFFSET 0
7
- #define LAZY_BOUNDS 1
8
- #define IMAGE_COLOR 2
9
- #define USER_DEFAULTS 3
10
-
11
- /* shared global */
12
- extern const rgba not_a_color_v;
13
-
14
- /* color and pixel related functions */
15
- rgba find_color_from_string(char * try_color);
16
- bool cmp_color(rgba color1, rgba color2);
17
- bool cmp_color_with_tolerance(rgba color1, rgba color2, float tolerance);
18
- void color_copy(float * source, float * dest);
19
- rgba get_pixel_color(texture_info * tex, int x, int y) ;
20
- float* get_pixel_data(texture_info * tex, int x, int y);
21
- void set_pixel_color(rgba * pixel_color, texture_info * tex, int x, int y);
22
- void zero_color(float * tex);
23
- bool not_a_color(rgba color1);
24
- bool is_a_color(rgba color1);
25
- VALUE convert_rgba_to_rb_color(rgba * pix);
26
- rgba convert_rb_color_to_rgba(VALUE cval);
27
- VALUE gosu_color_class();
28
- bool is_gosu_color(VALUE try_color);
29
- bool is_rb_raw_color(VALUE cval);
30
- bool not_rb_raw_color(VALUE cval);
31
- rgba convert_gosu_to_rgba_color(VALUE gcolor);
32
- VALUE convert_rgba_to_gosu_color(rgba * pix);
33
-
34
-
35
- VALUE save_rgba_to_image_local_color(VALUE image, rgba color);
36
- rgba convert_image_local_color_to_rgba(VALUE image);
37
-
38
-
39
- /* string/symbol related functions */
40
- char* lowercase(char*);
41
- char* sym2string(VALUE);
42
- VALUE string2sym(char*);
43
-
44
- /* is it a hash? */
45
- bool is_a_hash(VALUE try_hash);
46
-
47
- /* is an array? */
48
- bool is_an_array(VALUE try_array);
49
-
50
- /* is a num? */
51
- bool is_a_num(VALUE try_num);
52
-
53
- /* helpful C wrapper for rb_hash_aref */
54
- VALUE get_from_hash(VALUE hash, char * sym);
55
-
56
- /* a wrapper for rb_hash_aset */
57
- VALUE set_hash_value(VALUE hash, char * sym, VALUE val);
58
-
59
- /* a wrapper for rb_hash_delete */
60
- VALUE delete_from_hash(VALUE hash, char * sym);
61
-
62
- /* does the hash key 'sym' map to value 'val'? */
63
- bool hash_value_is(VALUE hash, char * sym, VALUE val);
64
-
65
- /* determine whether (1) hash is a T_HASH (2) the sym exists in the hash */
66
- bool has_optional_hash_arg(VALUE hash, char * sym);
67
-
68
-
69
- /* helpful C wrapper for rb_array_store */
70
- VALUE set_array_value(VALUE array, int index, VALUE val);
71
-
72
- /* helpful C wrapper for rb_array_entry */
73
- VALUE get_from_array(VALUE array, int index);
74
-
75
- /* set the lazy_bounds ivar for an image */
76
- VALUE set_ivar_array(VALUE obj, char * ivar, int argc, ...);
77
-
78
- /* initialize lazy_bounds */
79
- void init_lazy_bounds(VALUE image);
80
-
81
- /* initialize the image_local var array */
82
- VALUE init_image_local(VALUE image);
83
-
84
- /* return an image local variable */
85
- VALUE get_image_local(VALUE image, int name);
86
-
87
- /* set an image local variable */
88
- void set_image_local(VALUE image, int name, VALUE val);
89
-
90
- /* error checking functions */
91
- void check_mask(VALUE mask);
92
-
93
- void check_image(VALUE image);
94
-
95
- /* is try_image a Gosu::Image ? */
96
- bool is_gosu_image(VALUE try_image);
97
-
98
-
99
- /* make boundaries sane */
100
- void constrain_boundaries(int * x0, int * y0, int * x1, int * y1, int width, int height);
101
-
102
- /* line clipping */
103
- void cohen_sutherland_clip (int * x0, int * y0,int * x1, int * y1, int xmin, int ymin,
104
- int xmax, int ymax);
105
-
106
- /* check if point is bound by rect and inner thickness */
107
- bool bound_by_rect_and_inner(int x, int y, int x0, int y0, int x1, int y1, int inner);
108
-
109
- /* check if point is bound by rect */
110
- bool bound_by_rect(int x, int y, int x0, int y0, int x1, int y1);
111
-
112
- /* calculate the array offset for a given pixel */
113
- int calc_pixel_offset(texture_info * tex, int x, int y);
114
-
115
- /* calculate the array offset for a given pixel in an action context */
116
- int calc_pixel_offset_for_action(action_struct * cur, texture_info * tex, int x, int y);
117
-
118
- /* return a pointer to a new texture */
119
- float* allocate_texture(int width, int height);
120
-
121
- /* other function prototypes, get info for a texture */
122
- void get_texture_info(VALUE image, texture_info * tex);
123
-
124
- /* ensure gl_tex_info returns non nil */
125
- VALUE check_for_texture_info(VALUE image);
126
-
127
- /* responsible for syncing a subimage to gl */
128
- void sync_to_gl(int tex_name, int x_offset, int y_offset, int width, int height, void * sub);
129
-
130
- /* create a subtexture and sync to gl */
131
- void create_subtexture_and_sync_to_gl(image_bounds * img_bounds, texture_info * tex);
132
-
133
- float * get_image_chunk(texture_info * tex, int xmin, int ymin, int xmax, int ymax);
134
-
135
- rgba get_pixel_color_from_chunk(float * chunk, int width, int height, int x, int y);
136
-
137
- /* from Texture.cpp in Gosu Graphics folder */
138
- unsigned max_quad_size(void);
139
-
140
- /* point utils */
141
- bool is_a_point(VALUE try_point);
142
- VALUE point_x(VALUE point);
143
- VALUE point_y(VALUE point);
144
-
145
- /* mathematical utils, used by bezier curves */
146
- double power(float base, int exp);
147
- unsigned fact(int n);
148
- unsigned comb(int n, int k);
149
- unsigned perm(int n, int r);
150
-
151
- double bernstein(int n, int k, float u);
152
-
153
- #endif
1
+ #ifndef GUARD_UTILS_H
2
+ #define GUARD_UTILS_H
3
+
4
+
5
+ /* for use with get_image_local, and set_image_local */
6
+ #define DRAW_OFFSET 0
7
+ #define LAZY_BOUNDS 1
8
+ #define IMAGE_COLOR 2
9
+ #define USER_DEFAULTS 3
10
+
11
+ /* shared global */
12
+ extern const rgba not_a_color_v;
13
+
14
+ /* color and pixel related functions */
15
+ rgba find_color_from_string(char * try_color);
16
+ bool cmp_color(rgba color1, rgba color2);
17
+ bool cmp_color_with_tolerance(rgba color1, rgba color2, float tolerance);
18
+ void color_copy(float * source, float * dest);
19
+ rgba get_pixel_color(texture_info * tex, int x, int y) ;
20
+ float* get_pixel_data(texture_info * tex, int x, int y);
21
+ void set_pixel_color(rgba * pixel_color, texture_info * tex, int x, int y);
22
+ void zero_color(float * tex);
23
+ bool not_a_color(rgba color1);
24
+ bool is_a_color(rgba color1);
25
+ VALUE convert_rgba_to_rb_color(rgba * pix);
26
+ rgba convert_rb_color_to_rgba(VALUE cval);
27
+ VALUE gosu_color_class();
28
+ bool is_gosu_color(VALUE try_color);
29
+ bool is_rb_raw_color(VALUE cval);
30
+ bool not_rb_raw_color(VALUE cval);
31
+ rgba convert_gosu_to_rgba_color(VALUE gcolor);
32
+ VALUE convert_rgba_to_gosu_color(rgba * pix);
33
+
34
+
35
+ VALUE save_rgba_to_image_local_color(VALUE image, rgba color);
36
+ rgba convert_image_local_color_to_rgba(VALUE image);
37
+
38
+
39
+ /* string/symbol related functions */
40
+ char* lowercase(char*);
41
+ char* sym2string(VALUE);
42
+ VALUE string2sym(char*);
43
+
44
+ /* is it a hash? */
45
+ bool is_a_hash(VALUE try_hash);
46
+
47
+ /* is an array? */
48
+ bool is_an_array(VALUE try_array);
49
+
50
+ /* is a num? */
51
+ bool is_a_num(VALUE try_num);
52
+
53
+ /* helpful C wrapper for rb_hash_aref */
54
+ VALUE get_from_hash(VALUE hash, char * sym);
55
+
56
+ /* a wrapper for rb_hash_aset */
57
+ VALUE set_hash_value(VALUE hash, char * sym, VALUE val);
58
+
59
+ /* a wrapper for rb_hash_delete */
60
+ VALUE delete_from_hash(VALUE hash, char * sym);
61
+
62
+ /* does the hash key 'sym' map to value 'val'? */
63
+ bool hash_value_is(VALUE hash, char * sym, VALUE val);
64
+
65
+ /* determine whether (1) hash is a T_HASH (2) the sym exists in the hash */
66
+ bool has_optional_hash_arg(VALUE hash, char * sym);
67
+
68
+
69
+ /* helpful C wrapper for rb_array_store */
70
+ VALUE set_array_value(VALUE array, int index, VALUE val);
71
+
72
+ /* helpful C wrapper for rb_array_entry */
73
+ VALUE get_from_array(VALUE array, int index);
74
+
75
+ /* set the lazy_bounds ivar for an image */
76
+ VALUE set_ivar_array(VALUE obj, char * ivar, int argc, ...);
77
+
78
+ /* initialize lazy_bounds */
79
+ void init_lazy_bounds(VALUE image);
80
+
81
+ /* initialize the image_local var array */
82
+ VALUE init_image_local(VALUE image);
83
+
84
+ /* return an image local variable */
85
+ VALUE get_image_local(VALUE image, int name);
86
+
87
+ /* set an image local variable */
88
+ void set_image_local(VALUE image, int name, VALUE val);
89
+
90
+ /* error checking functions */
91
+ void check_mask(VALUE mask);
92
+
93
+ void check_image(VALUE image);
94
+
95
+ /* is try_image a Gosu::Image ? */
96
+ bool is_gosu_image(VALUE try_image);
97
+
98
+
99
+ /* make boundaries sane */
100
+ void constrain_boundaries(int * x0, int * y0, int * x1, int * y1, int width, int height);
101
+
102
+ /* line clipping */
103
+ void cohen_sutherland_clip (int * x0, int * y0,int * x1, int * y1, int xmin, int ymin,
104
+ int xmax, int ymax);
105
+
106
+ /* check if point is bound by rect and inner thickness */
107
+ bool bound_by_rect_and_inner(int x, int y, int x0, int y0, int x1, int y1, int inner);
108
+
109
+ /* check if point is bound by rect */
110
+ bool bound_by_rect(int x, int y, int x0, int y0, int x1, int y1);
111
+
112
+ /* calculate the array offset for a given pixel */
113
+ int calc_pixel_offset(texture_info * tex, int x, int y);
114
+
115
+ /* calculate the array offset for a given pixel in an action context */
116
+ int calc_pixel_offset_for_action(action_struct * cur, texture_info * tex, int x, int y);
117
+
118
+ /* return a pointer to a new texture */
119
+ float* allocate_texture(int width, int height);
120
+
121
+ /* other function prototypes, get info for a texture */
122
+ void get_texture_info(VALUE image, texture_info * tex);
123
+
124
+ /* ensure gl_tex_info returns non nil */
125
+ VALUE check_for_texture_info(VALUE image);
126
+
127
+ /* responsible for syncing a subimage to gl */
128
+ void sync_to_gl(int tex_name, int x_offset, int y_offset, int width, int height, void * sub);
129
+
130
+ /* create a subtexture and sync to gl */
131
+ void create_subtexture_and_sync_to_gl(image_bounds * img_bounds, texture_info * tex);
132
+
133
+ float * get_image_chunk(texture_info * tex, int xmin, int ymin, int xmax, int ymax);
134
+
135
+ rgba get_pixel_color_from_chunk(float * chunk, int width, int height, int x, int y);
136
+
137
+ /* from Texture.cpp in Gosu Graphics folder */
138
+ unsigned max_quad_size(void);
139
+
140
+ /* point utils */
141
+ bool is_a_point(VALUE try_point);
142
+ VALUE point_x(VALUE point);
143
+ VALUE point_y(VALUE point);
144
+
145
+ /* mathematical utils, used by bezier curves */
146
+ double power(float base, int exp);
147
+ unsigned fact(int n);
148
+ unsigned comb(int n, int k);
149
+ unsigned perm(int n, int r);
150
+
151
+ double bernstein(int n, int k, float u);
152
+
153
+ #endif
@@ -1,164 +1,147 @@
1
- # to bring in String#each_char for 1.8
2
- if RUBY_VERSION =~ /1.8/
3
- require 'jcode'
4
- end
5
-
6
- # setup will be executed straight after Gosu::Image instantiation
7
- TexPlay::on_setup do
8
- @turtle_pos = TexPlay::TPPoint.new(width / 2, height / 2 )
9
- @turtle_angle = 0
10
- end
11
-
12
-
13
- TexPlay::create_macro(:move_to) do |x, y|
14
- capture {
15
- @turtle_pos.x = x
16
- @turtle_pos.y = y
17
- }
18
- end
19
-
20
- TexPlay::create_macro(:move_rel) do |dx, dy|
21
- capture {
22
- @turtle_pos.x += dx
23
- @turtle_pos.y += dy
24
- }
25
- end
26
-
27
- TexPlay::create_macro(:line_to) do |x, y, *other|
28
- capture {
29
- line(@turtle_pos.x, @turtle_pos.y, x, y, *other)
30
-
31
- @turtle_pos.x, @turtle_pos.y = x, y
32
- }
33
- end
34
-
35
- TexPlay::create_macro(:line_rel) do |dx, dy, *other|
36
- capture {
37
- x = @turtle_pos.x + dx
38
- y = @turtle_pos.y + dy
39
-
40
- line(@turtle_pos.x, @turtle_pos.y, x, y, *other)
41
-
42
- @turtle_pos.x, @turtle_pos.y = x, y
43
- }
44
- end
45
-
46
- TexPlay::create_macro(:turn_to) do |a|
47
- capture {
48
- @turtle_angle = a
49
- }
50
- end
51
-
52
- TexPlay::create_macro(:turn) do |da|
53
- capture {
54
- @turtle_angle += da
55
- }
56
- end
57
-
58
- TexPlay::create_macro(:forward) do |dist, *other|
59
- capture {
60
- visible = other.shift
61
-
62
- radians_per_degree = 0.0174532925199433
63
-
64
- x = @turtle_pos.x + dist * Math::cos(radians_per_degree * @turtle_angle)
65
- y = @turtle_pos.y + dist * Math::sin(radians_per_degree * @turtle_angle)
66
-
67
- if(visible) then
68
- line_to(x, y, *other)
69
- else
70
- move_to(x, y)
71
- end
72
- }
73
- end
74
-
75
- # L-System code
76
- # adding LSystem class to TexPlay module
77
- class TexPlay::LSystem
78
- def initialize(&block)
79
- @rules = {}
80
-
81
- instance_eval(&block) if block
82
- end
83
-
84
- def rule(new_rule)
85
- @rules.merge!(new_rule)
86
- end
87
-
88
- def atom(new_atom)
89
- @atom = new_atom
90
- end
91
-
92
- def angle(new_angle=nil)
93
- return @angle if !new_angle
94
- @angle = new_angle
95
- end
96
-
97
- def produce_string(order)
98
- order = order[:order]
99
- string = @atom.dup
100
-
101
- order.times do
102
- i = 0
103
- while(i < string.length)
104
- sub = @rules[string[i, 1]]
105
-
106
- string[i] = sub if sub
107
-
108
- i += sub ? sub.length : 1
109
- end
110
- end
111
-
112
- string
113
- end
114
- end
115
-
116
- # L-System macro
117
- TexPlay::create_macro(:lsystem) do |x, y, system, options|
118
- capture {
119
- theta = system.angle
120
- turtle_stack = []
121
- move_to(x, y)
122
- line_length = options[:line_length] || 1
123
-
124
- system.produce_string(options).each_char do |v|
125
-
126
- case v
127
- when "F"
128
- forward(line_length, true)
129
- when "+"
130
- turn(theta)
131
- when "-"
132
- turn(-theta)
133
- when "["
134
- turtle_stack.push([@turtle_pos.dup, @turtle_angle])
135
- when "]"
136
- @turtle_pos, @turtle_angle = turtle_stack.pop
137
- end
138
- end
139
- }
140
- end
141
-
142
- # Scaling
143
- # uses nearest-neighbour
144
- TexPlay::create_macro(:splice_and_scale) do |img, cx, cy, *options|
145
- options = options.first ? options.first : {}
146
-
147
- options = {
148
- :color_control => proc do |c1, c2, x, y|
149
- factor = options[:factor] || 1
150
- factor_x = options[:factor_x] || factor
151
- factor_y = options[:factor_y] || factor
152
-
153
- x = factor_x * (x - cx) + cx
154
- y = factor_y * (y - cy) + cy
155
-
156
- rect x, y, x + factor_x, y + factor_y, :color => c2, :fill => true
157
- :none
158
- end
159
- }.merge!(options)
160
-
161
- splice img, cx, cy, options
162
-
163
- self
164
- end
1
+ # to bring in String#each_char for 1.8
2
+ if RUBY_VERSION =~ /1.8/
3
+ require 'jcode'
4
+ end
5
+
6
+ # setup will be executed straight after Gosu::Image instantiation
7
+ TexPlay::on_setup do
8
+ @turtle_pos = TexPlay::TPPoint.new(width / 2, height / 2 )
9
+ @turtle_angle = 0
10
+ end
11
+
12
+
13
+ TexPlay::create_macro(:move_to) do |x, y|
14
+ @turtle_pos.x = x
15
+ @turtle_pos.y = y
16
+ end
17
+
18
+ TexPlay::create_macro(:move_rel) do |dx, dy|
19
+ @turtle_pos.x += dx
20
+ @turtle_pos.y += dy
21
+ end
22
+
23
+ TexPlay::create_macro(:line_to) do |x, y, *other|
24
+ line(@turtle_pos.x, @turtle_pos.y, x, y, *other)
25
+ @turtle_pos.x, @turtle_pos.y = x, y
26
+ end
27
+
28
+ TexPlay::create_macro(:line_rel) do |dx, dy, *other|
29
+ x = @turtle_pos.x + dx
30
+ y = @turtle_pos.y + dy
31
+
32
+ line(@turtle_pos.x, @turtle_pos.y, x, y, *other)
33
+
34
+ @turtle_pos.x, @turtle_pos.y = x, y
35
+ end
36
+
37
+ TexPlay::create_macro(:turn_to) do |a|
38
+ @turtle_angle = a
39
+ end
40
+
41
+ TexPlay::create_macro(:turn) do |da|
42
+ @turtle_angle += da
43
+ end
44
+
45
+ TexPlay::create_macro(:forward) do |dist, *other|
46
+ visible = other.shift
47
+
48
+ radians_per_degree = 0.0174532925199433
49
+
50
+ x = @turtle_pos.x + dist * Math::cos(radians_per_degree * @turtle_angle)
51
+ y = @turtle_pos.y + dist * Math::sin(radians_per_degree * @turtle_angle)
52
+
53
+ if(visible) then
54
+ line_to(x, y, *other)
55
+ else
56
+ move_to(x, y)
57
+ end
58
+ end
59
+
60
+ # L-System code
61
+ # adding LSystem class to TexPlay module
62
+ class TexPlay::LSystem
63
+ def initialize(&block)
64
+ @rules = {}
65
+
66
+ instance_eval(&block) if block
67
+ end
68
+
69
+ def rule(new_rule)
70
+ @rules.merge!(new_rule)
71
+ end
72
+
73
+ def atom(new_atom)
74
+ @atom = new_atom
75
+ end
76
+
77
+ def angle(new_angle=nil)
78
+ return @angle if !new_angle
79
+ @angle = new_angle
80
+ end
81
+
82
+ def produce_string(order)
83
+ order = order[:order]
84
+ string = @atom.dup
85
+
86
+ order.times do
87
+ i = 0
88
+ while(i < string.length)
89
+ sub = @rules[string[i, 1]]
90
+
91
+ string[i] = sub if sub
92
+
93
+ i += sub ? sub.length : 1
94
+ end
95
+ end
96
+
97
+ string
98
+ end
99
+ end
100
+
101
+ # L-System macro
102
+ TexPlay::create_macro(:lsystem) do |x, y, system, options|
103
+ theta = system.angle
104
+ turtle_stack = []
105
+ move_to(x, y)
106
+ line_length = options[:line_length] || 1
107
+
108
+ system.produce_string(options).each_char do |v|
109
+
110
+ case v
111
+ when "F"
112
+ forward(line_length, true)
113
+ when "+"
114
+ turn(theta)
115
+ when "-"
116
+ turn(-theta)
117
+ when "["
118
+ turtle_stack.push([@turtle_pos.dup, @turtle_angle])
119
+ when "]"
120
+ @turtle_pos, @turtle_angle = turtle_stack.pop
121
+ end
122
+ end
123
+ end
124
+
125
+ # Scaling
126
+ # uses nearest-neighbour
127
+ TexPlay::create_macro(:splice_and_scale) do |img, cx, cy, *options|
128
+ options = options.first ? options.first : {}
129
+
130
+ options = {
131
+ :color_control => proc do |c1, c2, x, y|
132
+ factor = options[:factor] || 1
133
+ factor_x = options[:factor_x] || factor
134
+ factor_y = options[:factor_y] || factor
135
+
136
+ x = factor_x * (x - cx) + cx
137
+ y = factor_y * (y - cy) + cy
138
+
139
+ rect x, y, x + factor_x, y + factor_y, :color => c2, :fill => true
140
+ :none
141
+ end
142
+ }.merge!(options)
143
+
144
+ splice img, cx, cy, options
145
+
146
+ self
147
+ end