texplay 0.2.983pre2-i386-mswin32 → 0.3.0-i386-mswin32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/Rakefile +41 -49
  2. data/examples/common.rb +13 -2
  3. data/examples/example_alpha_blend.rb +1 -3
  4. data/examples/example_bezier.rb +1 -2
  5. data/examples/example_blank.rb +1 -3
  6. data/examples/example_cache.rb +1 -3
  7. data/examples/example_color_transform.rb +1 -3
  8. data/examples/example_color_transform_circle.rb +1 -3
  9. data/examples/example_darken.rb +1 -4
  10. data/examples/example_dup.rb +1 -4
  11. data/examples/example_each.rb +1 -4
  12. data/examples/example_effect.rb +1 -2
  13. data/examples/example_fill.rb +1 -2
  14. data/examples/example_fill_old.rb +1 -2
  15. data/examples/example_fluent.rb +1 -3
  16. data/examples/example_font.rb +1 -3
  17. data/examples/example_gen_eval.rb +1 -2
  18. data/examples/example_hash_arguments.rb +1 -2
  19. data/examples/example_ippa.rb +1 -3
  20. data/examples/example_light.rb +1 -3
  21. data/examples/example_light_multiply.rb +1 -3
  22. data/examples/example_lsystem.rb +1 -1
  23. data/examples/example_melt.rb +1 -3
  24. data/examples/example_meyet.rb +1 -3
  25. data/examples/example_polyline.rb +1 -2
  26. data/examples/example_scale.rb +1 -3
  27. data/examples/example_select.rb +1 -3
  28. data/examples/example_select2.rb +1 -4
  29. data/examples/example_simple.rb +1 -3
  30. data/examples/example_splice.rb +2 -4
  31. data/examples/example_sync.rb +1 -2
  32. data/examples/example_tiles.rb +1 -3
  33. data/examples/example_trace.rb +1 -2
  34. data/examples/example_transparent.rb +1 -3
  35. data/examples/example_transparent2.rb +1 -3
  36. data/examples/example_transparent3.rb +1 -3
  37. data/examples/example_turtle.rb +1 -2
  38. data/examples/example_weird.rb +1 -2
  39. data/examples/example_window_render_to_image.rb +41 -0
  40. data/examples/example_window_to_blob.rb +2 -5
  41. data/ext/texplay/actions.c +1006 -0
  42. data/ext/texplay/actions.h +60 -0
  43. data/ext/texplay/bindings.c +1186 -0
  44. data/ext/texplay/bindings.h +46 -0
  45. data/ext/texplay/cache.c +118 -0
  46. data/ext/texplay/cache.h +24 -0
  47. data/ext/texplay/compat.h +27 -0
  48. data/ext/texplay/extconf.rb +28 -0
  49. data/ext/texplay/gen_eval.c +211 -0
  50. data/ext/texplay/gen_eval.h +20 -0
  51. data/ext/texplay/graphics_utils.c +1244 -0
  52. data/ext/texplay/graphics_utils.h +22 -0
  53. data/ext/texplay/object2module.c +171 -0
  54. data/ext/texplay/object2module.h +11 -0
  55. data/ext/texplay/texplay.c +216 -0
  56. data/ext/texplay/texplay.h +148 -0
  57. data/ext/texplay/utils.c +887 -0
  58. data/ext/texplay/utils.h +153 -0
  59. data/lib/1.8/texplay.so +0 -0
  60. data/lib/1.9/texplay.so +0 -0
  61. data/lib/texplay.rb +271 -165
  62. data/lib/texplay/c_function_docs.rb +189 -0
  63. data/lib/texplay/version.rb +1 -1
  64. metadata +33 -21
  65. data/examples/example_window_to_texture.rb +0 -55
  66. data/lib/texplay/patches.rb +0 -4
@@ -0,0 +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
data/lib/1.8/texplay.so CHANGED
Binary file
data/lib/1.9/texplay.so CHANGED
Binary file
data/lib/texplay.rb CHANGED
@@ -1,225 +1,331 @@
1
1
 
2
2
  # (C) John Mair 2009, under the MIT licence
3
3
 
4
- begin
5
- require 'rubygems'
6
- rescue LoadError
7
- end
8
-
9
- direc = File.dirname(__FILE__)
4
+ direc = File.expand_path(File.dirname(__FILE__))
10
5
 
11
6
  # include gosu first
12
7
  require 'rbconfig'
13
8
  require 'gosu'
14
9
  require "#{direc}/texplay/version"
15
- require "#{direc}/texplay/patches"
16
10
 
17
11
  module TexPlay
18
- class << self
19
- def on_setup(&block)
20
- raise "need a block" if !block
21
-
22
- @__init_procs__ ||= []
23
- @__init_procs__.push(block)
24
- end
25
-
26
- def setup(receiver)
27
- if @__init_procs__ then
28
- @__init_procs__.each do |init_proc|
29
- receiver.instance_eval(&init_proc)
30
- end
31
- end
32
- end
33
-
34
- def create_image(window, width, height, options={})
35
- options = {
36
- :color => :alpha,
37
- :caching => false,
38
- }.merge!(options)
12
+ RENDER_CLEAR_COLOR = Gosu::Color.new(255, 0, 0, 0)
39
13
 
40
- raise ArgumentError, "Height and width must be positive" if height <= 0 or width <= 0
41
-
42
- img = Gosu::Image.new(window, EmptyImageStub.new(width, height), :caching => options[:caching])
43
- img.rect 0, 0, img.width - 1, img.height - 1, :color => options[:color], :fill => true
14
+ class << self
15
+ def on_setup(&block)
16
+ raise "need a block" if !block
17
+
18
+ @__init_procs__ ||= []
19
+ @__init_procs__.push(block)
20
+ end
44
21
 
45
- img
22
+ def setup(receiver)
23
+ if @__init_procs__ then
24
+ @__init_procs__.each do |init_proc|
25
+ receiver.instance_eval(&init_proc)
46
26
  end
27
+ end
28
+ end
47
29
 
48
- alias_method :create_blank_image, :create_image
49
-
50
- # Image can be :tileable, but it will break if it is tileable AND gets modified after creation.
51
- def from_blob(window, blob_data, width, height, options={})
52
- options = {
53
- :caching => @options[:caching],
54
- :tileable => false,
55
- }.merge!(options)
30
+ def create_image(window, width, height, options={})
31
+ options = {
32
+ :color => :alpha,
33
+ :caching => false,
34
+ }.merge!(options)
56
35
 
57
- raise ArgumentError, "Height and width must be positive (received #{width}x#{height})" if height <= 0 or width <= 0
36
+ raise ArgumentError, "Height and width must be positive" if height <= 0 or width <= 0
37
+
38
+ img = Gosu::Image.new(window, EmptyImageStub.new(width, height), :caching => options[:caching])
39
+ img.rect 0, 0, img.width - 1, img.height - 1, :color => options[:color], :fill => true
58
40
 
59
- expected_size = height * width * 4
60
- if blob_data.size != expected_size
61
- raise ArgumentError, "Blob data is not of the correct size (expected #{expected_size} but received #{blob_data.size} bytes)"
62
- end
41
+ img
42
+ end
63
43
 
64
- Gosu::Image.new(window, ImageStub.new(blob_data, width, height), options[:tileable], :caching => options[:caching])
65
- end
44
+ alias_method :create_blank_image, :create_image
66
45
 
67
- def set_options(options = {})
68
- @options.merge!(options)
69
- end
46
+ # Image can be :tileable, but it will break if it is tileable AND gets modified after creation.
47
+ def from_blob(window, blob_data, width, height, options={})
48
+ options = {
49
+ :caching => @options[:caching],
50
+ :tileable => false,
51
+ }.merge!(options)
70
52
 
71
- def get_options
72
- @options
73
- end
53
+ raise ArgumentError, "Height and width must be positive (received #{width}x#{height})" if height <= 0 or width <= 0
74
54
 
75
- # default values defined here
76
- def set_defaults
77
- @options = {
78
- :caching => true
79
- }
80
- end
55
+ expected_size = height * width * 4
56
+ if blob_data.size != expected_size
57
+ raise ArgumentError, "Blob data is not of the correct size (expected #{expected_size} but received #{blob_data.size} bytes)"
58
+ end
81
59
 
82
- def init
83
- set_defaults
84
- end
60
+ Gosu::Image.new(window, ImageStub.new(blob_data, width, height), options[:tileable], :caching => options[:caching])
85
61
  end
86
62
 
87
- module Colors
88
- Red = [1, 0, 0, 1]
89
- Green = [0, 1, 0, 1]
90
- Blue = [0, 0, 1, 1]
91
- Black = [0, 0, 0, 1]
92
- White = [1, 1, 1, 1]
93
- Grey = [0.5, 0.5, 0.5, 1]
94
- Alpha = [0, 0, 0, 0]
95
- Purple = [1, 0, 1, 1]
96
- Yellow = [1, 1, 0, 1]
97
- Cyan = [0, 1, 1, 1]
98
- Orange = [1, 0.5, 0, 1]
99
- Brown = [0.39, 0.26, 0.13, 1]
100
- Turquoise = [1, 0.6, 0.8, 1]
101
- Tyrian = [0.4, 0.007, 0.235, 1]
63
+ def set_options(options = {})
64
+ @options.merge!(options)
102
65
  end
103
- include Colors
104
66
 
105
- # extra instance methods defined in Ruby
106
-
107
- # clear an image (with an optional clear color)
108
- def clear(options = {})
109
- options = {
110
- :color => :alpha,
111
- :fill => true
112
- }.merge!(options)
67
+ def get_options
68
+ @options
69
+ end
113
70
 
114
- capture {
115
- rect 0, 0, width - 1, height - 1, options
116
-
117
- self
71
+ # default values defined here
72
+ def set_defaults
73
+ @options = {
74
+ :caching => true
118
75
  }
119
76
  end
120
-
121
- end
122
77
 
123
- # Used to create images from blob data.
124
- class ImageStub
78
+ def init
79
+ set_defaults
80
+ end
81
+ end
82
+
83
+ module Colors
84
+ Red = [1, 0, 0, 1]
85
+ Green = [0, 1, 0, 1]
86
+ Blue = [0, 0, 1, 1]
87
+ Black = [0, 0, 0, 1]
88
+ White = [1, 1, 1, 1]
89
+ Grey = [0.5, 0.5, 0.5, 1]
90
+ Alpha = [0, 0, 0, 0]
91
+ Purple = [1, 0, 1, 1]
92
+ Yellow = [1, 1, 0, 1]
93
+ Cyan = [0, 1, 1, 1]
94
+ Orange = [1, 0.5, 0, 1]
95
+ Brown = [0.39, 0.26, 0.13, 1]
96
+ Turquoise = [1, 0.6, 0.8, 1]
97
+ Tyrian = [0.4, 0.007, 0.235, 1]
98
+ end
99
+ include Colors
100
+
101
+ # extra instance methods defined in Ruby
102
+
103
+ # Clear an image.
104
+ #
105
+ # @option options :color (:alpha) Colour of the image.
106
+ # @return [Gosu::Image]
107
+ def clear(options = {})
108
+ options = {
109
+ :color => :alpha,
110
+ :fill => true
111
+ }.merge!(options)
112
+
113
+ capture {
114
+ rect 0, 0, width - 1, height - 1, options
115
+
116
+ self
117
+ }
118
+ end
119
+
120
+ # Used internally to create images from raw binary (blob) data (TexPlay::from_blob).
121
+ #
122
+ # This object duck-types an RMagick image (#rows, #columns, #to_blob), so that Gosu will import it.
123
+ class ImageStub
124
+ # @return [Integer]
125
125
  attr_reader :rows, :columns
126
-
126
+
127
+ # The first pixel in the blob will be at the top left hand corner of the created image, since that is the orientation
128
+ # of Gosu images.
129
+ #
130
+ # @param [String] blob_data Raw data string to import. Must be RGBA ordered, (4 * width * height) bytes in length.
131
+ # @param [Integer] width Number of pixels wide.
132
+ # @param [Integer] height Number of pixels high.
127
133
  def initialize(blob_data, width, height)
128
- @data, @columns, @rows = blob_data, width, height
134
+ @data, @columns, @rows = blob_data, width, height
129
135
  end
130
-
136
+
137
+ # @return [String]
131
138
  def to_blob
132
- @data
139
+ @data
133
140
  end
134
- end
135
-
136
- # Used to create blank images.
137
- # credit to philomory for this class
138
- class EmptyImageStub < ImageStub
141
+ end
142
+
143
+ # Used internally to create blank images (red/blue/green/alpha all 0) (TexPlay::create_image).
144
+ #
145
+ # Credit to philomory for this class.
146
+ class EmptyImageStub < ImageStub
147
+ # @param width (see ImageStub#initialize)
148
+ # @param height (see ImageStub#initialize)
139
149
  def initialize(width, height)
140
- super("\0" * (width * height * 4), width, height)
150
+ super("\0" * (width * height * 4), width, height)
141
151
  end
152
+ end
142
153
  end
143
154
 
144
155
  # bring in user-defined extensions to TexPlay
145
- direc = File.dirname(__FILE__)
146
156
  dlext = Config::CONFIG['DLEXT']
147
157
  begin
148
- if RUBY_VERSION && RUBY_VERSION =~ /1.9/
149
- require "#{direc}/1.9/texplay.#{dlext}"
150
- else
151
- require "#{direc}/1.8/texplay.#{dlext}"
152
- end
158
+ if RUBY_VERSION && RUBY_VERSION =~ /1.9/
159
+ require "#{direc}/1.9/texplay.#{dlext}"
160
+ else
161
+ require "#{direc}/1.8/texplay.#{dlext}"
162
+ end
153
163
  rescue LoadError => e
154
- require "#{direc}/texplay.#{dlext}"
164
+ require "#{direc}/texplay.#{dlext}"
155
165
  end
156
-
166
+
157
167
  require "#{direc}/texplay-contrib"
158
168
 
159
169
  # monkey patching the Gosu::Image class to add image manipulation functionality
160
170
  module Gosu
161
- class Image
171
+ class Image
172
+
173
+ # bring in the TexPlay image manipulation methods
174
+ include TexPlay
175
+
176
+ attr_reader :__window__
177
+ protected :__window__
178
+
179
+ class << self
180
+ alias_method :original_new, :new
162
181
 
163
- # bring in the TexPlay image manipulation methods
164
- include TexPlay
182
+ def new(*args, &block)
165
183
 
166
- attr_reader :__window__
184
+ options = args.last.is_a?(Hash) ? args.pop : {}
185
+ # invoke old behaviour
186
+ obj = original_new(*args, &block)
187
+
188
+ prepare_image(obj, args.first, options)
189
+ end
190
+
191
+ alias_method :original_from_text, :from_text
192
+
193
+ def from_text(*args, &block)
194
+
195
+ options = args.last.is_a?(Hash) ? args.pop : {}
196
+ # invoke old behaviour
197
+ obj = original_from_text(*args, &block)
198
+
199
+ prepare_image(obj, args.first, options)
200
+ end
201
+
202
+ def prepare_image(obj, window, options={})
203
+ options = {
204
+ :caching => TexPlay.get_options[:caching]
205
+ }.merge!(options)
167
206
 
168
- class << self
169
- alias_method :original_new, :new
170
-
171
- def new(*args, &block)
172
-
173
- options = args.last.is_a?(Hash) ? args.pop : {}
174
- # invoke old behaviour
175
- obj = original_new(*args, &block)
176
-
177
- prepare_image(obj, args.first, options)
178
- end
179
-
180
- alias_method :original_from_text, :from_text
181
-
182
- def from_text(*args, &block)
183
-
184
- options = args.last.is_a?(Hash) ? args.pop : {}
185
- # invoke old behaviour
186
- obj = original_from_text(*args, &block)
187
-
188
- prepare_image(obj, args.first, options)
189
- end
190
-
191
- def prepare_image(obj, window, options={})
192
- options = {
193
- :caching => TexPlay.get_options[:caching]
194
- }.merge!(options)
195
-
196
- # refresh the TexPlay image cache
197
- if obj.width <= (TexPlay::TP_MAX_QUAD_SIZE) &&
198
- obj.height <= (TexPlay::TP_MAX_QUAD_SIZE) && obj.quad_cached? then
199
- obj.refresh_cache if options[:caching]
200
- end
201
-
202
- # run custom setup
203
- TexPlay.setup(obj)
204
-
205
- obj.instance_variable_set(:@__window__, window)
206
-
207
- obj
208
- end
209
-
210
- private :prepare_image
207
+ # refresh the TexPlay image cache
208
+ if obj.width <= (TexPlay::TP_MAX_QUAD_SIZE) &&
209
+ obj.height <= (TexPlay::TP_MAX_QUAD_SIZE) && obj.quad_cached? then
210
+ obj.refresh_cache if options[:caching]
211
211
  end
212
+
213
+ # run custom setup
214
+ TexPlay.setup(obj)
215
+
216
+ obj.instance_variable_set(:@__window__, window)
217
+
218
+ obj
219
+ end
220
+
221
+ private :prepare_image
222
+ end
223
+
224
+ alias_method :rows, :height
225
+ alias_method :columns, :width
226
+ end
227
+
228
+ class Window
229
+ # Render directly into an existing image, optionally only to a specific region of that image.
230
+ #
231
+ # Since this operation utilises the window's back buffer, the image (or clipped area, if specified) cannot be larger than the
232
+ # window itself. Larger images can be rendered to only in separate sections using :clip_to areas, each no larger
233
+ # than the window).
234
+ #
235
+ # @note *Warning!* This operation will corrupt an area of the screen, at the bottom left corner, equal in size to the image rendered to (or the clipped area), so should be performed in #draw _before_ any other rendering.
236
+ #
237
+ # @note The final alpha of the image will be 255, regardless of what it started with or what is drawn onto it.
238
+ #
239
+ # @example
240
+ # class Gosu
241
+ # class Window
242
+ # def draw
243
+ # # Always render images before regular drawing to the screen.
244
+ # unless @rendered_image
245
+ # @rendered_image = TexPlay.create_image(self, 300, 300, :color => :blue)
246
+ # render_to_image(@rendered_image) do
247
+ # @an_image.draw 0, 0, 0
248
+ # @another_image.draw 130, 0, 0
249
+ # draw_line(0, 0, Color.new(255, 0, 0, 0), 100, 100, Color.new(255, 0, 0, 0), 0)
250
+ # @font.draw("Hello world!", 0, 50, 0)
251
+ # end
252
+ # end
253
+ #
254
+ # # Perform regular screen rendering.
255
+ # @rendered_image.draw 0, 0
256
+ # end
257
+ # end
258
+ # end
259
+ #
260
+ #
261
+ # @param [Gosu::Image] image Existing image to render onto.
262
+ # @option options [Array<Integer>] :clip_to ([0, 0, image.width, image.height]) Area of the image to render into. This area cannot be larger than the window, though the image may be.
263
+ # @return [Gosu::Image] The image that has been rendered to.
264
+ # @yield to a block that renders to the image.
265
+ def render_to_image(image, options = {})
266
+ raise ArgumentError, "image parameter must be a Gosu::Image to be rendered to" unless image.is_a? Gosu::Image
267
+ raise ArgumentError, "rendering block required" unless block_given?
268
+
269
+ options = {
270
+ :clip_to => [0, 0, image.width, image.height],
271
+ }.merge! options
272
+
273
+ texture_info = image.gl_tex_info
274
+ tex_name = texture_info.tex_name
275
+ x_offset = (texture_info.left * Gosu::MAX_TEXTURE_SIZE).to_i
276
+ y_offset = (texture_info.top * Gosu::MAX_TEXTURE_SIZE).to_i
277
+
278
+ raise ArgumentError, ":clip_to rectangle must contain exactly 4 elements" unless options[:clip_to].size == 4
279
+
280
+ left, top, width, height = *(options[:clip_to].map {|n| n.to_i })
281
+
282
+ raise ArgumentError, ":clip_to rectangle cannot be wider or taller than the window" unless width <= self.width and height <= self.height
283
+ raise ArgumentError, ":clip_to rectangle width and height must be positive" unless width > 0 and height > 0
212
284
 
213
- alias_method :rows, :height
214
- alias_method :columns, :width
285
+ right = left + width - 1
286
+ bottom = top + height - 1
287
+
288
+ unless (0...image.width).include? left and (0...image.width).include? right and
289
+ (0...image.height).include? top and (0...image.height).include? bottom
290
+ raise ArgumentError, ":clip_to rectangle out of bounds of the image"
291
+ end
292
+
293
+ # Since to_texture copies an inverted copy of the screen, what the user renders needs to be inverted first.
294
+ scale(1, -1) do
295
+ translate(-left, -top - self.height) do
296
+ # TODO: Once Gosu is fixed, we can just pass width/height to clip_to
297
+ clip_to(left, top, width, height) do
298
+ # Draw over the background (which is assumed to be blank) with the original image texture,
299
+ # to get us to the base image.
300
+ image.draw(0, 0, 0)
301
+ flush
302
+
303
+ # Allow the user to overwrite the texture.
304
+ yield
305
+ end
306
+
307
+ # Copy the modified texture back from the screen buffer to the image.
308
+ to_texture(tex_name, x_offset + left, y_offset + top, 0, 0, width, height)
309
+
310
+ # Clear the clipped zone to black again, ready for the regular screen drawing.
311
+ # Quad can be a pixel out, so just make sure with a slightly larger shape.
312
+ draw_quad(left - 2, top - 2, TexPlay::RENDER_CLEAR_COLOR,
313
+ right + 2, top - 2, TexPlay::RENDER_CLEAR_COLOR,
314
+ right + 2, bottom + 2, TexPlay::RENDER_CLEAR_COLOR,
315
+ left - 2, bottom + 2, TexPlay::RENDER_CLEAR_COLOR)
215
316
  end
317
+ end
318
+
319
+ image
320
+ end
321
+ end
216
322
  end
217
323
 
218
324
  # a bug in ruby 1.8.6 rb_eval_string() means i must define this here (rather than in texplay.c)
219
325
  class Proc
220
- def __context__
221
- eval('self', self.binding)
222
- end
326
+ def __context__
327
+ eval('self', self.binding)
328
+ end
223
329
  end
224
330
 
225
331