texplay 0.2.800 → 0.2.900

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