texplay 0.3.1 → 0.3.3pre2

Sign up to get free protection for your applications and to get access to all the features.
data/.gemtest ADDED
File without changes
data/Rakefile CHANGED
@@ -1,17 +1,14 @@
1
- $LOAD_PATH.unshift File.join(File.expand_path(__FILE__), '..')
2
-
1
+ direc = File.dirname(__FILE__)
2
+ dlext = Config::CONFIG['DLEXT']
3
+ project_name = "texplay"
3
4
 
4
5
  require 'rake/clean'
5
6
  require 'rake/gempackagetask'
7
+ require "#{direc}/lib/#{project_name}/version"
6
8
 
7
- # get the texplay version
8
- require './lib/texplay/version'
9
-
10
- direc = File.dirname(__FILE__)
11
- dlext = Config::CONFIG['DLEXT']
12
-
13
- CLEAN.include("ext/**/*.#{dlext}", "ext/**/*.log", "ext/**/*.o", "ext/**/*~", "ext/**/*#*", "ext/**/*.obj", "ext/**/*.def", "ext/**/*.pdb")
14
9
  CLOBBER.include("**/*.#{dlext}", "**/*~", "**/*#*", "**/*.log", "**/*.o")
10
+ CLEAN.include("ext/**/*.#{dlext}", "ext/**/*.log", "ext/**/*.o", "ext/**/*~",
11
+ "ext/**/*#*", "ext/**/*.obj", "ext/**/*.def", "ext/**/*.pdb")
15
12
 
16
13
  def apply_spec_defaults(s)
17
14
  s.name = "texplay"
@@ -23,13 +20,17 @@ def apply_spec_defaults(s)
23
20
  s.description = s.summary
24
21
  s.require_path = 'lib'
25
22
  s.add_dependency("gosu",">=0.7.25")
23
+ s.add_development_dependency("bacon",">=1.1.0")
26
24
  s.homepage = "http://banisterfiend.wordpress.com/2008/08/23/texplay-an-image-manipulation-tool-for-ruby-and-gosu/"
27
25
  s.has_rdoc = 'yard'
28
- s.files = FileList["Rakefile", "README.markdown", "CHANGELOG",
26
+ s.files = Dir["Rakefile", "README.markdown", "CHANGELOG",
29
27
  "lib/**/*.rb", "ext/**/extconf.rb", "ext/**/*.h", "ext/**/*.c",
30
- "examples/*.rb", "examples/media/*", "spec/*.rb"].to_a
28
+ "examples/*.rb", "examples/media/*", "test/*.rb", "live/*rb", ".gemtest"]
31
29
  end
32
30
 
31
+ task :test do
32
+ sh "bacon -k #{direc}/test/texplay_spec.rb"
33
+ end
33
34
 
34
35
  [:mingw32, :mswin32].each do |v|
35
36
  namespace v do
@@ -50,7 +51,7 @@ namespace :ruby do
50
51
  spec = Gem::Specification.new do |s|
51
52
  apply_spec_defaults(s)
52
53
  s.platform = Gem::Platform::RUBY
53
- s.extensions = ["ext/texplay/extconf.rb"]
54
+ s.extensions = ["ext/#{project_name}/extconf.rb"]
54
55
  end
55
56
 
56
57
  Rake::GemPackageTask.new(spec) do |pkg|
@@ -58,9 +59,31 @@ namespace :ruby do
58
59
  pkg.need_tar = false
59
60
  end
60
61
  end
62
+
63
+ directories = ["#{direc}/lib/1.8", "#{direc}/lib/1.9"]
64
+ directories.each { |d| directory d }
65
+
66
+ desc "build the 1.8 and 1.9 binaries from source and copy to lib/"
67
+ task :compile => directories do
68
+ build_for = proc do |pik_ver, ver|
69
+ sh %{ \
70
+ c:\\devkit\\devkitvars.bat && \
71
+ pik #{pik_ver} && \
72
+ ruby extconf.rb && \
73
+ make clean && \
74
+ make && \
75
+ cp *.so #{direc}/lib/#{ver} \
76
+ }
77
+ end
61
78
 
79
+ chdir("#{direc}/ext/#{project_name}") do
80
+ build_for.call("187", "1.8")
81
+ build_for.call("192", "1.9")
82
+ end
83
+ end
84
+
62
85
  desc "build all platform gems at once"
63
- task :gems => ["mingw32:gem", "mswin32:gem", "ruby:gem"]
86
+ task :gems => [:clean, :rmgems, "mingw32:gem", "mswin32:gem", "ruby:gem"]
64
87
 
65
88
  desc "remove all platform gems"
66
89
  task :rmgems => ["ruby:clobber_package"]
@@ -73,3 +96,4 @@ task :pushgems => :gems do
73
96
  end
74
97
  end
75
98
  end
99
+
@@ -14,6 +14,7 @@
14
14
  static void initialize_action_struct(action_struct * cur, VALUE hash_arg, sync sync_mode);
15
15
  static void process_common_hash_args(action_struct * cur, VALUE * hash_arg, sync sync_mode, bool primary);
16
16
  static void prepare_drawing_mode(action_struct * cur);
17
+ static void prepare_alpha_blend(action_struct * cur);
17
18
  static void prepare_fill_texture(action_struct * cur);
18
19
  static void prepare_color_control(action_struct * cur);
19
20
  static void prepare_color_select(action_struct * cur);
@@ -343,6 +344,8 @@ initialize_action_struct(action_struct * cur, VALUE hash_arg, sync sync_mode)
343
344
  cur->pen.has_color_control_proc = false;
344
345
  cur->pen.has_color_control_transform = false;
345
346
  cur->pen.has_source_texture = false;
347
+
348
+ /* alpha blending */
346
349
  cur->pen.alpha_blend = false;
347
350
 
348
351
  /* set static color control transformations to defaults */
@@ -471,8 +474,48 @@ process_common_hash_args(action_struct * cur, VALUE * hash_arg, sync sync_mode,
471
474
  prepare_fill_texture(cur);
472
475
 
473
476
  /* does the user want to blend alpha values ? */
474
- if(get_from_hash(*hash_arg, "alpha_blend") == Qtrue)
475
- cur->pen.alpha_blend = true;
477
+ prepare_alpha_blend(cur);
478
+ }
479
+
480
+ static void
481
+ prepare_alpha_blend(action_struct * cur)
482
+ {
483
+ if(has_optional_hash_arg(cur->hash_arg, "alpha_blend")) {
484
+
485
+ VALUE blend_mode = get_from_hash(cur->hash_arg, "alpha_blend");
486
+
487
+ /* true is equivalent to default blend mode, 'source' */
488
+ if(blend_mode == Qtrue)
489
+ blend_mode = string2sym("source");
490
+
491
+ /* where false or nil is passed */
492
+ if(!RTEST(blend_mode)) {
493
+ cur->pen.alpha_blend = false;
494
+ return;
495
+ }
496
+
497
+ cur->pen.alpha_blend = true;
498
+
499
+ Check_Type(blend_mode, T_SYMBOL);
500
+
501
+ if(blend_mode == string2sym("source")) {
502
+ cur->pen.alpha_blend_mode = source;
503
+ }
504
+ else if(blend_mode == string2sym("dest")) {
505
+ cur->pen.alpha_blend_mode = dest;
506
+ }
507
+ else if(blend_mode == string2sym("source_with_fixed_alpha")) {
508
+ cur->pen.alpha_blend_mode = source_with_fixed_alpha;
509
+ }
510
+ else if(blend_mode == string2sym("dest_with_fixed_alpha")) {
511
+ cur->pen.alpha_blend_mode = dest_with_fixed_alpha;
512
+ }
513
+ else
514
+ rb_raise(rb_eArgError, "unrecognized blend mode: %s\n.",
515
+ sym2string(blend_mode));
516
+
517
+ }
518
+
476
519
 
477
520
  }
478
521
 
@@ -591,10 +634,6 @@ prepare_color_control(action_struct * cur)
591
634
  if(is_an_array(try_add)) {
592
635
 
593
636
  cur->pen.color_add = convert_rb_color_to_rgba(try_add);
594
- /* cur->pen.color_add.red = NUM2DBL(get_from_array(try_add, 0)); */
595
- /* cur->pen.color_add.green = NUM2DBL(get_from_array(try_add, 1)); */
596
- /* cur->pen.color_add.blue = NUM2DBL(get_from_array(try_add, 2)); */
597
- /* cur->pen.color_add.alpha = NUM2DBL(get_from_array(try_add, 3)); */
598
637
 
599
638
  cur->pen.has_color_control_transform = true;
600
639
  }
@@ -602,11 +641,6 @@ prepare_color_control(action_struct * cur)
602
641
 
603
642
  cur->pen.color_mult = convert_rb_color_to_rgba(try_mult);
604
643
 
605
- /* cur->pen.color_mult.red = NUM2DBL(get_from_array(try_mult, 0)); */
606
- /* cur->pen.color_mult.green = NUM2DBL(get_from_array(try_mult, 1)); */
607
- /* cur->pen.color_mult.blue = NUM2DBL(get_from_array(try_mult, 2)); */
608
- /* cur->pen.color_mult.alpha = NUM2DBL(get_from_array(try_mult, 3)); */
609
-
610
644
  cur->pen.has_color_control_transform = true;
611
645
  }
612
646
 
@@ -1068,33 +1102,68 @@ apply_color_control_transform(action_struct * payload, texture_info * tex, int x
1068
1102
  static rgba
1069
1103
  apply_alpha_blend(action_struct * payload, texture_info * tex, int x, int y, rgba blended_pixel)
1070
1104
  {
1071
- rgba dest_pixel = get_pixel_color(tex, x, y);
1072
- rgba finished_pixel;
1073
-
1105
+ rgba dest_pixel = get_pixel_color(tex, x, y);
1106
+ rgba finished_pixel;
1074
1107
 
1075
- if (not_a_color(blended_pixel))
1076
- return blended_pixel;
1108
+ if (not_a_color(blended_pixel))
1109
+ return blended_pixel;
1110
+
1111
+ alpha_blend_mode_t blend_mode = payload->pen.alpha_blend_mode;
1077
1112
 
1078
- /* alpha blending is nothing more than a weighted average of src and dest pixels
1079
- based on source alpha value */
1080
- /* NB: destination alpha value is ignored */
1113
+ switch(blend_mode)
1114
+ {
1115
+ case source:
1116
+ case source_with_fixed_alpha:
1117
+ /** TO DO: rewrite this using sse2 instructions **/
1118
+ finished_pixel.red = blended_pixel.alpha * blended_pixel.red + (1 - blended_pixel.alpha)
1119
+ * dest_pixel.red;
1120
+
1121
+ finished_pixel.green = blended_pixel.alpha * blended_pixel.green + (1 - blended_pixel.alpha)
1122
+ * dest_pixel.green;
1123
+
1124
+ finished_pixel.blue = blended_pixel.alpha * blended_pixel.blue + (1 - blended_pixel.alpha)
1125
+ * dest_pixel.blue;
1126
+
1127
+ if(blend_mode == source) {
1128
+ finished_pixel.alpha = blended_pixel.alpha * blended_pixel.alpha + (1 - blended_pixel.alpha)
1129
+ * dest_pixel.alpha;
1130
+ }
1131
+ else {
1081
1132
 
1082
- /** TO DO: rewrite this using sse2 instructions **/
1083
- finished_pixel.red = blended_pixel.alpha * blended_pixel.red + (1 - blended_pixel.alpha)
1133
+ // fixed alpha
1134
+ finished_pixel.alpha = dest_pixel.alpha;
1135
+ }
1136
+
1137
+ break;
1138
+ case dest:
1139
+ case dest_with_fixed_alpha:
1140
+ finished_pixel.red = dest_pixel.alpha * blended_pixel.red + (1 - dest_pixel.alpha)
1084
1141
  * dest_pixel.red;
1085
1142
 
1086
- finished_pixel.green = blended_pixel.alpha * blended_pixel.green + (1 - blended_pixel.alpha)
1143
+ finished_pixel.green = dest_pixel.alpha * blended_pixel.green + (1 - dest_pixel.alpha)
1087
1144
  * dest_pixel.green;
1088
1145
 
1089
- finished_pixel.blue = blended_pixel.alpha * blended_pixel.blue + (1 - blended_pixel.alpha)
1146
+ finished_pixel.blue = dest_pixel.alpha * blended_pixel.blue + (1 - dest_pixel.alpha)
1090
1147
  * dest_pixel.blue;
1091
1148
 
1149
+ if(blend_mode == dest) {
1150
+ finished_pixel.alpha = dest_pixel.alpha * blended_pixel.alpha + (1 - dest_pixel.alpha)
1151
+ * dest_pixel.alpha;
1152
+ }
1153
+ else {
1092
1154
 
1093
- finished_pixel.alpha = blended_pixel.alpha * blended_pixel.alpha + (1 - blended_pixel.alpha)
1094
- * dest_pixel.alpha;
1155
+ // fixed alpha
1156
+ finished_pixel.alpha = dest_pixel.alpha;
1157
+ }
1158
+
1159
+ break;
1160
+ default:
1161
+ rb_raise(rb_eRuntimeError,
1162
+ "apply_alpha_blend() impossible error. got %d\n", blend_mode);
1095
1163
 
1164
+ }
1096
1165
 
1097
- return finished_pixel;
1166
+ return finished_pixel;
1098
1167
  }
1099
1168
 
1100
1169
  /* NEW from utils.c */
@@ -29,15 +29,15 @@
29
29
 
30
30
  /* enums */
31
31
  typedef enum e_bool {
32
- false, true
32
+ false, true
33
33
  } bool;
34
34
 
35
35
  typedef enum e_color {
36
- red, green, blue, alpha
36
+ red, green, blue, alpha
37
37
  } color_t;
38
38
 
39
39
  typedef enum e_sync_mode {
40
- lazy_sync, eager_sync, no_sync
40
+ lazy_sync, eager_sync, no_sync
41
41
  } sync;
42
42
 
43
43
 
@@ -54,6 +54,10 @@ typedef enum {
54
54
  difference, exclusion
55
55
  } draw_mode;
56
56
 
57
+ typedef enum {
58
+ source, dest, source_with_fixed_alpha, dest_with_fixed_alpha
59
+ } alpha_blend_mode_t;
60
+
57
61
  /* structs */
58
62
  typedef struct s_rgba {
59
63
  float red, green, blue, alpha;
@@ -67,80 +71,81 @@ typedef struct {
67
71
 
68
72
  /* stores image data */
69
73
  typedef struct {
70
- int width, height;
71
- float top, left;
72
- int tname;
73
- float * td_array;
74
- int yincr, firstpixel;
75
- int x_offset, y_offset;
76
- VALUE image;
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;
77
81
  } texture_info;
78
82
 
79
83
 
80
84
  /* convenience macro */
81
85
  #define IMAGE_BOUNDS(X) ((image_bounds *) (X))
82
86
  typedef struct {
83
- int xmin;
84
- int ymin;
85
- int xmax;
86
- int ymax;
87
+ int xmin;
88
+ int ymin;
89
+ int xmax;
90
+ int ymax;
87
91
  } image_bounds;
88
92
 
89
93
 
90
94
  typedef struct action_struct {
91
- int xmin, ymin, xmax, ymax;
92
- sync sync_mode;
95
+ int xmin, ymin, xmax, ymax;
96
+ sync sync_mode;
93
97
 
94
- /* pointer to associated texture */
95
- /* a bit of a kludge having this here
96
- since it's only being used by convert_image_local_color_to_rgba */
97
- texture_info * tex;
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;
98
102
 
99
- VALUE hash_arg;
100
-
101
- /* action color */
102
- rgba color;
103
+ VALUE hash_arg;
103
104
 
104
- /* pen data */
105
- struct {
105
+ /* action color */
106
+ rgba color;
106
107
 
107
- /* color control, dynamic */
108
- bool has_color_control_proc;
109
- VALUE color_control_proc;
110
- int color_control_arity;
108
+ /* pen data */
109
+ struct {
111
110
 
112
- /* color control, static */
113
- bool has_color_control_transform;
114
- rgba color_mult;
115
- rgba color_add;
111
+ /* color control, dynamic */
112
+ bool has_color_control_proc;
113
+ VALUE color_control_proc;
114
+ int color_control_arity;
116
115
 
117
- /* texture fill */
118
- bool has_source_texture;
119
- texture_info source_tex;
116
+ /* color control, static */
117
+ bool has_color_control_transform;
118
+ rgba color_mult;
119
+ rgba color_add;
120
120
 
121
- /* lerp */
122
- bool has_lerp;
123
- float lerp;
121
+ /* texture fill */
122
+ bool has_source_texture;
123
+ texture_info source_tex;
124
124
 
125
- /* alpha blend */
126
- bool alpha_blend;
125
+ /* lerp */
126
+ bool has_lerp;
127
+ float lerp;
127
128
 
128
- /* drawing mode */
129
- bool has_drawing_mode;
130
- draw_mode drawing_mode;
131
-
132
- /* tolerance */
133
- bool has_tolerance;
134
- float tolerance;
135
-
136
- /* color selection */
137
- bool has_color_select;
138
- rgba_list source_select;
139
- rgba_list source_ignore;
140
- rgba_list dest_select;
141
- rgba_list dest_ignore;
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;
142
147
 
143
- } pen;
148
+ } pen;
144
149
 
145
150
  } action_struct;
146
151
 
@@ -1,171 +1,164 @@
1
- begin
2
- require 'rubygems'
3
- rescue LoadError
4
- end
5
-
6
- require 'texplay'
7
-
8
1
  # to bring in String#each_char for 1.8
9
2
  if RUBY_VERSION =~ /1.8/
10
- require 'jcode'
3
+ require 'jcode'
11
4
  end
12
5
 
13
6
  # setup will be executed straight after Gosu::Image instantiation
14
7
  TexPlay::on_setup do
15
- @turtle_pos = TexPlay::TPPoint.new(width / 2, height / 2 )
16
- @turtle_angle = 0
8
+ @turtle_pos = TexPlay::TPPoint.new(width / 2, height / 2 )
9
+ @turtle_angle = 0
17
10
  end
18
11
 
19
12
 
20
13
  TexPlay::create_macro(:move_to) do |x, y|
21
- capture {
22
- @turtle_pos.x = x
23
- @turtle_pos.y = y
24
- }
14
+ capture {
15
+ @turtle_pos.x = x
16
+ @turtle_pos.y = y
17
+ }
25
18
  end
26
19
 
27
20
  TexPlay::create_macro(:move_rel) do |dx, dy|
28
- capture {
29
- @turtle_pos.x += dx
30
- @turtle_pos.y += dy
31
- }
21
+ capture {
22
+ @turtle_pos.x += dx
23
+ @turtle_pos.y += dy
24
+ }
32
25
  end
33
26
 
34
27
  TexPlay::create_macro(:line_to) do |x, y, *other|
35
- capture {
36
- line(@turtle_pos.x, @turtle_pos.y, x, y, *other)
28
+ capture {
29
+ line(@turtle_pos.x, @turtle_pos.y, x, y, *other)
37
30
 
38
- @turtle_pos.x, @turtle_pos.y = x, y
39
- }
31
+ @turtle_pos.x, @turtle_pos.y = x, y
32
+ }
40
33
  end
41
34
 
42
35
  TexPlay::create_macro(:line_rel) do |dx, dy, *other|
43
- capture {
44
- x = @turtle_pos.x + dx
45
- y = @turtle_pos.y + dy
36
+ capture {
37
+ x = @turtle_pos.x + dx
38
+ y = @turtle_pos.y + dy
46
39
 
47
- line(@turtle_pos.x, @turtle_pos.y, x, y, *other)
40
+ line(@turtle_pos.x, @turtle_pos.y, x, y, *other)
48
41
 
49
- @turtle_pos.x, @turtle_pos.y = x, y
50
- }
42
+ @turtle_pos.x, @turtle_pos.y = x, y
43
+ }
51
44
  end
52
45
 
53
46
  TexPlay::create_macro(:turn_to) do |a|
54
- capture {
55
- @turtle_angle = a
56
- }
47
+ capture {
48
+ @turtle_angle = a
49
+ }
57
50
  end
58
51
 
59
52
  TexPlay::create_macro(:turn) do |da|
60
- capture {
61
- @turtle_angle += da
62
- }
53
+ capture {
54
+ @turtle_angle += da
55
+ }
63
56
  end
64
57
 
65
58
  TexPlay::create_macro(:forward) do |dist, *other|
66
- capture {
67
- visible = other.shift
59
+ capture {
60
+ visible = other.shift
68
61
 
69
- radians_per_degree = 0.0174532925199433
62
+ radians_per_degree = 0.0174532925199433
70
63
 
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)
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)
73
66
 
74
- if(visible) then
75
- line_to(x, y, *other)
76
- else
77
- move_to(x, y)
78
- end
79
- }
67
+ if(visible) then
68
+ line_to(x, y, *other)
69
+ else
70
+ move_to(x, y)
71
+ end
72
+ }
80
73
  end
81
74
 
82
75
  # L-System code
83
76
  # adding LSystem class to TexPlay module
84
77
  class TexPlay::LSystem
85
- def initialize(&block)
86
- @rules = {}
87
-
88
- instance_eval(&block) if block
89
- end
78
+ def initialize(&block)
79
+ @rules = {}
90
80
 
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
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]]
107
105
 
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
106
+ string[i] = sub if sub
118
107
 
119
- string
108
+ i += sub ? sub.length : 1
109
+ end
120
110
  end
111
+
112
+ string
113
+ end
121
114
  end
122
115
 
123
116
  # L-System macro
124
117
  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
- }
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
+ }
147
140
  end
148
141
 
149
142
  # Scaling
150
143
  # uses nearest-neighbour
151
144
  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
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
171
164
  end