texplay 0.2.722 → 0.2.800

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -39,29 +39,29 @@ Rake::ExtensionTask.new('texplay', specification) do |ext|
39
39
  end
40
40
 
41
41
 
42
- # comment this when want to build normal gems.
43
- # only have this code uncommented when building mswin32 and mingw32
44
- # binary gems
45
- # specification = Gem::Specification.new do |s|
46
- # s.name = "texplay"
47
- # s.summary = "TexPlay is a light-weight image manipulation framework for Ruby and Gosu"
48
- # s.version = TexPlay::VERSION
49
- # s.date = Time.now.strftime '%Y-%m-%d'
50
- # s.author = "John Mair (banisterfiend)"
51
- # s.email = 'jrmair@gmail.com'
52
- # s.description = s.summary
53
- # s.require_path = 'lib'
54
- # s.add_dependency("gosu",">=0.7.14")
55
- # s.platform = 'i386-mingw32'
56
- # s.homepage = "http://banisterfiend.wordpress.com/2008/08/23/texplay-an-image-manipulation-tool-for-ruby-and-gosu/"
57
- # s.has_rdoc = false
42
+ #comment this when want to build normal gems.
43
+ #only have this code uncommented when building mswin32 and mingw32
44
+ #binary gems
45
+ # specification = Gem::Specification.new do |s|
46
+ # s.name = "texplay"
47
+ # s.summary = "TexPlay is a light-weight image manipulation framework for Ruby and Gosu"
48
+ # s.version = TexPlay::VERSION
49
+ # s.date = Time.now.strftime '%Y-%m-%d'
50
+ # s.author = "John Mair (banisterfiend)"
51
+ # s.email = 'jrmair@gmail.com'
52
+ # s.description = s.summary
53
+ # s.require_path = 'lib'
54
+ # s.add_dependency("gosu",">=0.7.14")
55
+ # s.platform = 'i386-mswin32'
56
+ # s.homepage = "http://banisterfiend.wordpress.com/2008/08/23/texplay-an-image-manipulation-tool-for-ruby-and-gosu/"
57
+ # s.has_rdoc = false
58
58
 
59
- # s.files = ["Rakefile", "README.markdown", "CHANGELOG",
60
- # "lib/texplay.rb", "lib/texplay-contrib.rb", "lib/texplay/version.rb", "lib/1.8/texplay.so",
61
- # "lib/1.9/texplay.so"] +
59
+ # s.files = ["Rakefile", "README.markdown", "CHANGELOG",
60
+ # "lib/texplay.rb", "lib/texplay-contrib.rb", "lib/texplay/version.rb", "lib/1.8/texplay.so",
61
+ # "lib/1.9/texplay.so"] +
62
62
  # FileList["examples/*.rb", "examples/media/*"].to_a
63
63
  # end
64
-
64
+
65
65
  Rake::GemPackageTask.new(specification) do |package|
66
66
  package.need_zip = false
67
67
  package.need_tar = false
@@ -30,13 +30,12 @@ class W < Gosu::Window
30
30
  @y2 += 1
31
31
 
32
32
 
33
- @copy2.splice @img, 0, 0, :crop => [@x2 - @rad, @y2 - @rad, @x2 + @rad, @y2 + @rad]
34
- @copy.splice @img, 0, 0, :crop => [@x - @rad, @y - @rad, @x + @rad, @y + @rad]
33
+ @copy2.splice @img, 0, 0, :crop => [@x2 - @rad, @y2 - @rad, @x2 + @rad, @y2 + @rad], :sync_mode => :no_sync
34
+ @copy.splice @img, 0, 0, :crop => [@x - @rad, @y - @rad, @x + @rad, @y + @rad], :sync_mode => :no_sync
35
35
  @img.
36
- circle @x, @y, @rad, :fill => true,
37
- :color_control => { :mult => [1.0, 0.5, 0.5, 1] }
36
+ circle @x, @y, @rad, :fill => true, :lerp => 0.3, :color => :red
38
37
 
39
- # circle @x2, @y2, @rad, :fill => true,
38
+ @img.circle @x2, @y2, @rad, :fill => true, :lerp => 0.3, :color => :blue
40
39
  # :color_control => { :mult => [0.3, 0.9, 0.3, 1] }
41
40
 
42
41
 
@@ -0,0 +1,23 @@
1
+ require 'rubygems'
2
+ require 'common'
3
+ require 'texplay'
4
+
5
+
6
+ class W < Gosu::Window
7
+ def initialize
8
+ super(1024, 768, false, 20)
9
+ @img = TexPlay.create_image(self, 500, 500).fill(3,3, :color => :alpha)
10
+ @img.rect 100, 100, 300 , 300, :color => :blue, :fill => true
11
+ puts (@img.line 0,0, 100, 100, :trace => { :until_color => :blue }).inspect
12
+ end
13
+
14
+ def draw
15
+ @img.draw 100, 50,1
16
+ end
17
+
18
+ end
19
+
20
+
21
+ w = W.new
22
+ w.show
23
+
@@ -6,24 +6,15 @@ require 'texplay'
6
6
  class W < Gosu::Window
7
7
  def initialize
8
8
  super(1024, 768, false, 20)
9
- @img = Gosu::Image.new(self, "#{Common::MEDIA}/bird.png")
10
- @green = Gosu::Image.new(self, "#{Common::MEDIA}/gob.png")
11
- ### @img = Gosu::Image.new(self, "gob.png")
12
- #@img = TexPlay.create_image(self, 500, 500).fill(0,0, :color => :red)
13
-
14
- @img.splice @green, 0, 0, :alpha_blend => true
15
- puts @img.get_pixel 15, 15
16
- # @img.rect 0, 0, @img.width, @img.height, :texture => @gob, :fill => true, :alpha_blend => true
17
-
9
+ @img = Gosu::Image.new(self, "#{Common::MEDIA}/gob.png")
10
+ @img.rect 0, 10, 300, 300, :color => :blue, :fill => true, :mode => :softlight
18
11
  end
19
12
 
20
13
  def draw
21
14
  @img.draw 100, 50,1
22
15
  end
23
-
24
16
  end
25
17
 
26
-
27
18
  w = W.new
28
19
  w.show
29
20
 
@@ -12,7 +12,24 @@
12
12
 
13
13
 
14
14
  /** line_do_action, bresenham's algorithm **/
15
- void
15
+ typedef enum { no_mode, until_color, while_color} trace_mode_type;
16
+
17
+ static inline bool
18
+ is_trace_match(rgba c, rgba trace_color, trace_mode_type trace_mode)
19
+ {
20
+ if(trace_mode == while_color) {
21
+ if(!cmp_color(c, trace_color))
22
+ return true;
23
+ }
24
+ else if(trace_mode == until_color) {
25
+ if(cmp_color(c, trace_color))
26
+ return true;
27
+ }
28
+
29
+ return false;
30
+ }
31
+
32
+ trace_match
16
33
  line_do_action(int x1, int y1, int x2, int y2, texture_info * tex, VALUE hash_arg,
17
34
  sync sync_mode, bool primary, action_struct * payload)
18
35
  {
@@ -21,11 +38,39 @@ line_do_action(int x1, int y1, int x2, int y2, texture_info * tex, VALUE hash_ar
21
38
  action_struct cur;
22
39
  int thickness = 1;
23
40
 
24
- draw_prologue(&cur, tex, x1, y1,
25
- x2, y2, &hash_arg, sync_mode, primary, &payload);
41
+ bool has_trace = false;
42
+ rgba trace_color;
43
+ trace_mode_type trace_mode = no_mode;
44
+
45
+
26
46
 
27
47
  if(has_optional_hash_arg(hash_arg, "thickness"))
28
48
  thickness = NUM2INT(get_from_hash(hash_arg, "thickness"));
49
+
50
+ if(has_optional_hash_arg(hash_arg, "trace") && primary) {
51
+ VALUE trace_hash = get_from_hash(hash_arg, "trace");
52
+
53
+ /* we're tracing (not drawing) */
54
+ has_trace = true;
55
+
56
+ /* since we're not drawing, no need to sync */
57
+ sync_mode = no_sync;
58
+
59
+ if(has_optional_hash_arg(trace_hash, "until_color")) {
60
+ VALUE c = get_from_hash(trace_hash, "until_color");
61
+ trace_color = convert_rb_color_to_rgba(c);
62
+ trace_mode = until_color;
63
+ }
64
+ else if(has_optional_hash_arg(trace_hash, "while_color")) {
65
+ VALUE c = get_from_hash(trace_hash, "while_color");
66
+ trace_color = convert_rb_color_to_rgba(c);
67
+ trace_mode = while_color;
68
+ }
69
+ }
70
+
71
+ draw_prologue(&cur, tex, x1, y1,
72
+ x2, y2, &hash_arg, sync_mode, primary, &payload);
73
+
29
74
 
30
75
  /* clip the line */
31
76
  cohen_sutherland_clip(&x1, &y1, &x2, &y2, 0, 0, tex->width - 1, tex->height - 1);
@@ -50,7 +95,14 @@ line_do_action(int x1, int y1, int x2, int y2, texture_info * tex, VALUE hash_ar
50
95
  F = 2 * H - W;
51
96
  while(x != x2) {
52
97
  if(thickness <= 1) {
98
+ if(!has_trace)
53
99
  set_pixel_color_with_style(payload, tex, x, y);
100
+ else {
101
+ rgba c = get_pixel_color(tex, x, y);
102
+
103
+ if (is_trace_match(c, trace_color, trace_mode))
104
+ return (trace_match) { x, y, c };
105
+ }
54
106
  }
55
107
  else {
56
108
  set_hash_value(hash_arg, "fill", Qtrue);
@@ -71,7 +123,14 @@ line_do_action(int x1, int y1, int x2, int y2, texture_info * tex, VALUE hash_ar
71
123
  while(y != y2 ) {
72
124
 
73
125
  if(thickness <= 1) {
126
+ if(!has_trace)
74
127
  set_pixel_color_with_style(payload, tex, x, y);
128
+ else {
129
+ rgba c = get_pixel_color(tex, x, y);
130
+
131
+ if (is_trace_match(c, trace_color, trace_mode))
132
+ return (trace_match) { x, y, c };
133
+ }
75
134
  }
76
135
  else {
77
136
  set_hash_value(hash_arg, "fill", Qtrue);
@@ -89,7 +148,14 @@ line_do_action(int x1, int y1, int x2, int y2, texture_info * tex, VALUE hash_ar
89
148
  }
90
149
 
91
150
  if(thickness <= 1) {
92
- set_pixel_color_with_style(payload, tex, x2, y2);
151
+ if(!has_trace)
152
+ set_pixel_color_with_style(payload, tex, x2, y2);
153
+ else {
154
+ rgba c = get_pixel_color(tex, x, y);
155
+
156
+ if (is_trace_match(c, trace_color, trace_mode))
157
+ return (trace_match) { x, y, c };
158
+ }
93
159
  }
94
160
  else {
95
161
  set_hash_value(hash_arg, "fill", Qtrue);
@@ -97,6 +163,8 @@ line_do_action(int x1, int y1, int x2, int y2, texture_info * tex, VALUE hash_ar
97
163
 
98
164
  }
99
165
  draw_epilogue(&cur, tex, primary);
166
+
167
+ return (trace_match) { .x = -1, .y = -1 };
100
168
  }
101
169
  /** end line **/
102
170
 
@@ -1,9 +1,17 @@
1
1
  #ifndef GUARD_ACTIONS_H
2
2
  #define GUARD_ACTIONS_H
3
3
 
4
+ #include "texplay.h"
5
+
6
+ /* used by line_do_action */
7
+ typedef struct {
8
+ int x, y;
9
+ rgba color;
10
+ } trace_match;
11
+
4
12
 
5
13
  /* lines */
6
- void line_do_action(int, int, int, int, texture_info *, VALUE, sync, bool primary, action_struct * payload);
14
+ trace_match line_do_action(int, int, int, int, texture_info *, VALUE, sync, bool primary, action_struct * payload);
7
15
 
8
16
  /* circles */
9
17
  void circle_do_action(int, int, int, texture_info *, VALUE, sync, bool primary, action_struct * payload);
@@ -505,7 +505,18 @@ m_flood_fill(int argc, VALUE * argv, VALUE self)
505
505
 
506
506
  return self;
507
507
  }
508
-
508
+
509
+ static inline VALUE
510
+ convert_trace_match_to_ruby_array(trace_match match)
511
+ {
512
+ VALUE ary = rb_ary_new();
513
+
514
+ rb_ary_store(ary, 0, INT2FIX(match.x));
515
+ rb_ary_store(ary, 1, INT2FIX(match.y));
516
+ rb_ary_store(ary, 2, convert_rgba_to_rb_color(&match.color));
517
+
518
+ return ary;
519
+ }
509
520
 
510
521
  /* line action */
511
522
  VALUE
@@ -515,6 +526,7 @@ m_line(int argc, VALUE * argv, VALUE self)
515
526
  int last = argc - 1;
516
527
  VALUE options;
517
528
  texture_info tex;
529
+ trace_match match;
518
530
 
519
531
  ADJUST_SELF(self);
520
532
 
@@ -526,7 +538,14 @@ m_line(int argc, VALUE * argv, VALUE self)
526
538
 
527
539
  get_texture_info(self, &tex);
528
540
 
529
- line_do_action(x1, y1, x2, y2, &tex, options, sync_mode, true, NULL);
541
+ match = line_do_action(x1, y1, x2, y2, &tex, options, sync_mode, true, NULL);
542
+
543
+ if (has_optional_hash_arg(options, "trace")) {
544
+ if (match.x == -1)
545
+ return Qnil;
546
+ else
547
+ return convert_trace_match_to_ruby_array(match);
548
+ }
530
549
 
531
550
  return self;
532
551
  }
@@ -13,9 +13,13 @@
13
13
  /* small helper functions */
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
+ static void prepare_drawing_mode(action_struct * cur);
16
17
  static void prepare_fill_texture(action_struct * cur);
17
18
  static void prepare_color_control(action_struct * cur);
19
+ static rgba apply_lerp(action_struct * payload, texture_info * tex, int x, int y);
18
20
  static rgba apply_alpha_blend(action_struct * payload, texture_info * tex, int x, int y, rgba blended_pixel);
21
+ static rgba apply_drawing_mode(action_struct * payload, texture_info * tex, int x, int y);
22
+
19
23
  static rgba apply_color_control_transform(action_struct * payload, texture_info * tex, int x, int y);
20
24
  static rgba exec_color_control_proc(action_struct * cur, texture_info * tex, int x, int y, rgba blended_pixel);
21
25
  /* end helpers */
@@ -149,11 +153,16 @@ set_pixel_color_with_style(action_struct * payload, texture_info * tex, int x, i
149
153
 
150
154
  blended_pixel = payload->color;
151
155
 
156
+ /* for linear interpolation */
157
+ if(payload->pen.has_lerp) {
158
+ blended_pixel = apply_lerp(payload, tex, x, y);
159
+ }
160
+
152
161
  /* for color_control transform */
153
162
  if(payload->pen.has_color_control_transform)
154
163
  blended_pixel = apply_color_control_transform(payload, tex, x, y);
155
164
 
156
- /* for texture fill */
165
+ /* for texture fill */
157
166
  if(payload->pen.has_source_texture)
158
167
  blended_pixel = get_pixel_color(&payload->pen.source_tex,
159
168
  x % payload->pen.source_tex.width,
@@ -165,7 +174,10 @@ set_pixel_color_with_style(action_struct * payload, texture_info * tex, int x, i
165
174
 
166
175
 
167
176
  /* TO DO: do bitwise pixel combinations here */
168
-
177
+ if(payload->pen.has_drawing_mode) {
178
+ blended_pixel = apply_drawing_mode(payload, tex, x, y);
179
+ }
180
+
169
181
  /* TO DO: refactor into its own helper function
170
182
  & rewrite using sse2 */
171
183
  if(payload->pen.alpha_blend)
@@ -236,13 +248,13 @@ create_image(VALUE window, int width, int height)
236
248
  VALUE gosu = rb_const_get(rb_cObject, rb_intern("Gosu"));
237
249
  VALUE image = rb_const_get(gosu, rb_intern("Image"));
238
250
 
239
- VALUE TP = rb_const_get(rb_cObject, rb_intern("TexPlay"));
240
- VALUE EmptyImageStub = rb_const_get(TP, rb_intern("EmptyImageStub"));
251
+ VALUE tp = rb_const_get(rb_cObject, rb_intern("TexPlay"));
252
+ VALUE empty_image_stub = rb_const_get(tp, rb_intern("EmptyImageStub"));
241
253
 
242
254
  VALUE rmagick_img;
243
255
  VALUE new_image;
244
256
 
245
- rmagick_img = rb_funcall(EmptyImageStub, rb_intern("new"), 2, INT2FIX(width), INT2FIX(height));
257
+ rmagick_img = rb_funcall(empty_image_stub, rb_intern("new"), 2, INT2FIX(width), INT2FIX(height));
246
258
 
247
259
  new_image = rb_funcall(image, rb_intern("new"), 2, window, rmagick_img);
248
260
 
@@ -275,6 +287,12 @@ initialize_action_struct(action_struct * cur, VALUE hash_arg, sync sync_mode)
275
287
  cur->pen.color_add.green = 0.0;
276
288
  cur->pen.color_add.blue = 0.0;
277
289
  cur->pen.color_add.alpha = 0.0;
290
+
291
+ /* lerp is off by default */
292
+ cur->pen.has_lerp = false;
293
+
294
+ /* drawing mode is off by deafult */
295
+ cur->pen.has_drawing_mode = false;
278
296
  }
279
297
 
280
298
  /* TODO: fix this function below, it's too ugly and bulky and weird **/
@@ -315,6 +333,16 @@ process_common_hash_args(action_struct * cur, VALUE * hash_arg, sync sync_mode,
315
333
 
316
334
  cur->pen.has_color_control_transform = true;
317
335
  }
336
+
337
+ /* lerp */
338
+ if(RTEST(get_from_hash(*hash_arg, "lerp"))) {
339
+ cur->pen.lerp = NUM2DBL(get_from_hash(*hash_arg, "lerp"));
340
+
341
+ /* bounds */
342
+ if(cur->pen.lerp > 1.0) cur->pen.lerp = 1.0;
343
+ if(cur->pen.lerp < 0.0) cur->pen.lerp = 0.0;
344
+ cur->pen.has_lerp = true;
345
+ }
318
346
 
319
347
  /* sync mode */
320
348
  if(has_optional_hash_arg(*hash_arg, "sync_mode")) {
@@ -337,6 +365,9 @@ process_common_hash_args(action_struct * cur, VALUE * hash_arg, sync sync_mode,
337
365
 
338
366
  }
339
367
 
368
+ /* process drawing mode */
369
+ prepare_drawing_mode(cur);
370
+
340
371
  /* process the color_control block or transform (if there is one) */
341
372
  prepare_color_control(cur);
342
373
 
@@ -349,8 +380,96 @@ process_common_hash_args(action_struct * cur, VALUE * hash_arg, sync sync_mode,
349
380
 
350
381
  }
351
382
 
383
+ static void
384
+ prepare_drawing_mode(action_struct * cur)
385
+ {
386
+ if(is_a_hash(cur->hash_arg)) {
387
+ /* drawing mode */
388
+ if(has_optional_hash_arg(cur->hash_arg, "mode")) {
389
+ cur->pen.has_drawing_mode = true;
390
+
391
+ VALUE draw_mode = get_from_hash(cur->hash_arg, "mode");
352
392
 
353
393
 
394
+ Check_Type(draw_mode, T_SYMBOL);
395
+
396
+ if(draw_mode == string2sym("clear"))
397
+ cur->pen.drawing_mode = clear;
398
+
399
+ else if(draw_mode == string2sym("copy"))
400
+ cur->pen.drawing_mode = copy;
401
+
402
+ else if(draw_mode == string2sym("noop"))
403
+ cur->pen.drawing_mode = noop;
404
+
405
+ else if(draw_mode == string2sym("set"))
406
+ cur->pen.drawing_mode = set;
407
+
408
+ else if(draw_mode == string2sym("copy_inverted"))
409
+ cur->pen.drawing_mode = copy_inverted;
410
+
411
+ else if(draw_mode == string2sym("invert"))
412
+ cur->pen.drawing_mode = invert;
413
+
414
+ else if(draw_mode == string2sym("and_reverse"))
415
+ cur->pen.drawing_mode = and_reverse;
416
+
417
+ else if(draw_mode == string2sym("and"))
418
+ cur->pen.drawing_mode = and;
419
+
420
+ else if(draw_mode == string2sym("or"))
421
+ cur->pen.drawing_mode = or;
422
+
423
+ else if(draw_mode == string2sym("nand"))
424
+ cur->pen.drawing_mode = nand;
425
+
426
+ else if(draw_mode == string2sym("nor"))
427
+ cur->pen.drawing_mode = nor;
428
+
429
+ else if(draw_mode == string2sym("xor"))
430
+ cur->pen.drawing_mode = xor;
431
+
432
+ else if(draw_mode == string2sym("equiv"))
433
+ cur->pen.drawing_mode = equiv;
434
+
435
+ else if(draw_mode == string2sym("and_inverted"))
436
+ cur->pen.drawing_mode = and_inverted;
437
+
438
+ else if(draw_mode == string2sym("or_inverted"))
439
+ cur->pen.drawing_mode = or_inverted;
440
+
441
+ else if(draw_mode == string2sym("additive"))
442
+ cur->pen.drawing_mode = additive;
443
+ else if(draw_mode == string2sym("multiply"))
444
+ cur->pen.drawing_mode = multiply;
445
+ else if(draw_mode == string2sym("screen"))
446
+ cur->pen.drawing_mode = screen;
447
+ else if(draw_mode == string2sym("overlay"))
448
+ cur->pen.drawing_mode = overlay;
449
+ else if(draw_mode == string2sym("darken"))
450
+ cur->pen.drawing_mode = darken;
451
+ else if(draw_mode == string2sym("lighten"))
452
+ cur->pen.drawing_mode = lighten;
453
+ else if(draw_mode == string2sym("colordodge"))
454
+ cur->pen.drawing_mode = colordodge;
455
+ else if(draw_mode == string2sym("colorburn"))
456
+ cur->pen.drawing_mode = colorburn;
457
+ else if(draw_mode == string2sym("hardlight"))
458
+ cur->pen.drawing_mode = hardlight;
459
+ else if(draw_mode == string2sym("softlight"))
460
+ cur->pen.drawing_mode = softlight;
461
+ else if(draw_mode == string2sym("difference"))
462
+ cur->pen.drawing_mode = difference;
463
+ else if(draw_mode == string2sym("exclusion"))
464
+ cur->pen.drawing_mode = exclusion;
465
+ else
466
+ rb_raise(rb_eArgError, "unrecognized drawing mode: %s\n.",
467
+ sym2string(draw_mode));
468
+ }
469
+ }
470
+ }
471
+
472
+
354
473
  /* set action color to return value of color_control proc */
355
474
  static void
356
475
  prepare_color_control(action_struct * cur)
@@ -457,7 +576,316 @@ prepare_fill_texture(action_struct * payload)
457
576
  }
458
577
  }
459
578
 
579
+ /***********************************/
580
+ /**** drawing mode related code ****/
581
+ /***********************************/
582
+
583
+ typedef struct {
584
+ unsigned char red, green, blue, alpha;
585
+ } rgba_char;
586
+
587
+ static inline rgba_char
588
+ color_float_to_int_format(rgba c)
589
+ {
590
+ return (rgba_char) { c.red * 255,
591
+ c.green * 255,
592
+ c.blue * 255,
593
+ c.alpha * 255
594
+ };
595
+ }
596
+
597
+ static inline rgba
598
+ color_int_vals_to_float_format(unsigned char r, unsigned char g, unsigned char b,
599
+ unsigned char a)
600
+ {
601
+ return (rgba) { r / 255.0,
602
+ g / 255.0,
603
+ b / 255.0,
604
+ a / 255.0
605
+ };
606
+ }
607
+
608
+ /* using terminology from photoshop PDF. b=background, s=source */
609
+ static inline rgba
610
+ mode_multiply(rgba b, rgba s)
611
+ {
612
+ return (rgba) { b.red * s.red,
613
+ b.green * s.green,
614
+ b.blue * s.blue,
615
+ b.alpha * s.alpha };
616
+ }
617
+
618
+ static inline rgba
619
+ mode_screen(rgba b, rgba s)
620
+ {
621
+ return (rgba) { b.red + s.red - (b.red * s.red),
622
+ b.green + s.green - (b.green * s.green),
623
+ b.blue + s.blue - (b.blue * s.blue),
624
+ b.alpha + s.alpha - (b.alpha * s.alpha) };
625
+ }
626
+
627
+ static inline float
628
+ mode_hardlight_channel(float b, float s)
629
+ {
630
+ if (s <= 0.5)
631
+ return 2 * b * s;
632
+
633
+ else
634
+ return b + s - (b * s);
635
+ }
636
+
637
+ static inline rgba
638
+ mode_hardlight(rgba b, rgba s)
639
+ {
640
+ return (rgba) { mode_hardlight_channel(b.red, s.red),
641
+ mode_hardlight_channel(b.green, s.green),
642
+ mode_hardlight_channel(b.blue, s.blue),
643
+ mode_hardlight_channel(b.alpha, s.alpha) };
644
+ }
645
+
646
+ /* function from the photoshop PDF to implement soft lighting */
647
+ static inline float
648
+ D(float x)
649
+ {
650
+ if (x <= 0.25)
651
+ return ((16 * x - 12) * x + 4) * x;
652
+ else
653
+ return sqrt(x);
654
+ }
655
+
656
+ static inline float
657
+ mode_softlight_channel(float b, float s)
658
+ {
659
+ if (s <= 0.5)
660
+ return b - (1 - 2 * s) * b * (1 - b);
661
+ else
662
+ return b + (2 * s - 1) * (D(b) - b);
663
+ }
664
+
665
+ static inline rgba
666
+ mode_softlight(rgba b, rgba s)
667
+ {
668
+ return (rgba) { mode_softlight_channel(b.red, s.red),
669
+ mode_softlight_channel(b.green, s.green),
670
+ mode_softlight_channel(b.blue, s.blue),
671
+ mode_softlight_channel(b.alpha, s.alpha) };
672
+ }
673
+
674
+ static inline float
675
+ mode_colordodge_channel(float b, float s)
676
+ {
677
+ if (s < 1)
678
+ return MIN(1, b / (1 - s));
679
+ else
680
+ return 1;
681
+ }
682
+
683
+ static inline float
684
+ mode_colorburn_channel(float b, float s)
685
+ {
686
+ if (s > 0)
687
+ return 1 - MIN(1, (1 - b) / s);
688
+ else
689
+ return 0;
690
+ }
691
+
692
+ static rgba
693
+ apply_drawing_mode(action_struct * payload, texture_info * tex, int x, int y)
694
+ {
695
+ rgba finished_pixel;
696
+
697
+ rgba source_pixel = payload->color;
698
+ rgba dest_pixel = get_pixel_color(tex, x, y);
699
+
700
+ rgba_char dest_pixel_char = color_float_to_int_format(dest_pixel);
701
+ rgba_char source_pixel_char = color_float_to_int_format(source_pixel);
702
+
703
+ switch(payload->pen.drawing_mode)
704
+ {
705
+
706
+ /* bitwise blending functions */
707
+ case clear:
708
+ finished_pixel = (rgba) { 0, 0, 0, 0 };
709
+ break;
710
+ case copy:
711
+ finished_pixel = source_pixel;
712
+ break;
713
+ case noop:
714
+ finished_pixel = dest_pixel;
715
+ break;
716
+ case set:
717
+ finished_pixel = (rgba) { 1, 1, 1, 1 };
718
+ break;
719
+ case copy_inverted:
720
+ finished_pixel = color_int_vals_to_float_format(~source_pixel_char.red,
721
+ ~source_pixel_char.green,
722
+ ~source_pixel_char.blue,
723
+ ~source_pixel_char.alpha);
724
+ break;
725
+ case invert:
726
+ finished_pixel = color_int_vals_to_float_format(~dest_pixel_char.red,
727
+ ~dest_pixel_char.green,
728
+ ~dest_pixel_char.blue,
729
+ ~dest_pixel_char.alpha);
730
+
731
+ break;
732
+ case and_reverse:
733
+ finished_pixel = color_int_vals_to_float_format(source_pixel_char.red | ~dest_pixel_char.red,
734
+ source_pixel_char.green | ~dest_pixel_char.green,
735
+ source_pixel_char.blue | ~dest_pixel_char.blue,
736
+ source_pixel_char.alpha | ~dest_pixel_char.alpha);
737
+ break;
738
+ case and:
739
+ finished_pixel = color_int_vals_to_float_format(source_pixel_char.red & dest_pixel_char.red,
740
+ source_pixel_char.green & dest_pixel_char.green,
741
+ source_pixel_char.blue & dest_pixel_char.blue,
742
+ source_pixel_char.alpha & dest_pixel_char.alpha);
743
+ break;
744
+ case or:
745
+ finished_pixel = color_int_vals_to_float_format(source_pixel_char.red | dest_pixel_char.red,
746
+ source_pixel_char.green | dest_pixel_char.green,
747
+ source_pixel_char.blue | dest_pixel_char.blue,
748
+ source_pixel_char.alpha | dest_pixel_char.alpha);
749
+
750
+ break;
751
+ case nand:
752
+ finished_pixel = color_int_vals_to_float_format(~(source_pixel_char.red & dest_pixel_char.red),
753
+ ~(source_pixel_char.green & dest_pixel_char.green),
754
+ ~(source_pixel_char.blue & dest_pixel_char.blue),
755
+ ~(source_pixel_char.alpha & dest_pixel_char.alpha));
756
+
757
+ break;
758
+ case nor:
759
+ finished_pixel = color_int_vals_to_float_format(~(source_pixel_char.red | dest_pixel_char.red),
760
+ ~(source_pixel_char.green | dest_pixel_char.green),
761
+ ~(source_pixel_char.blue | dest_pixel_char.blue),
762
+ ~(source_pixel_char.alpha | dest_pixel_char.alpha));
763
+
764
+ break;
765
+ case xor:
766
+ finished_pixel = color_int_vals_to_float_format(source_pixel_char.red ^ dest_pixel_char.red,
767
+ source_pixel_char.green ^ dest_pixel_char.green,
768
+ source_pixel_char.blue ^ dest_pixel_char.blue,
769
+ source_pixel_char.alpha ^ dest_pixel_char.alpha);
770
+
771
+ break;
772
+ case equiv:
773
+ finished_pixel = color_int_vals_to_float_format(~(source_pixel_char.red ^ dest_pixel_char.red),
774
+ ~(source_pixel_char.green ^ dest_pixel_char.green),
775
+ ~(source_pixel_char.blue ^ dest_pixel_char.blue),
776
+ ~(source_pixel_char.alpha ^ dest_pixel_char.alpha));
777
+
778
+ break;
779
+ case and_inverted:
780
+ finished_pixel = color_int_vals_to_float_format(~source_pixel_char.red & dest_pixel_char.red,
781
+ ~source_pixel_char.green & dest_pixel_char.green,
782
+ ~source_pixel_char.blue & dest_pixel_char.blue,
783
+ ~source_pixel_char.alpha & dest_pixel_char.alpha);
784
+ break;
785
+ case or_inverted:
786
+ finished_pixel = color_int_vals_to_float_format(~source_pixel_char.red | dest_pixel_char.red,
787
+ ~source_pixel_char.green | dest_pixel_char.green,
788
+ ~source_pixel_char.blue | dest_pixel_char.blue,
789
+ ~source_pixel_char.alpha | dest_pixel_char.alpha);
790
+
791
+ break;
792
+
793
+ /* photoshop style blending functions */
794
+ case additive:
795
+ finished_pixel = (rgba) { MIN(source_pixel.red + dest_pixel.red, 1),
796
+ MIN(source_pixel.green + dest_pixel.green, 1),
797
+ MIN(source_pixel.blue + dest_pixel.blue, 1),
798
+ MIN(source_pixel.alpha + dest_pixel.alpha, 1) };
799
+ break;
800
+ case multiply:
801
+ finished_pixel = mode_multiply(dest_pixel, source_pixel);
802
+
803
+ break;
804
+ case screen:
805
+ finished_pixel = mode_screen(dest_pixel, source_pixel);
806
+
807
+ break;
808
+ case overlay:
809
+ finished_pixel = mode_hardlight(source_pixel, dest_pixel);
810
+
811
+ break;
812
+
813
+ case darken:
814
+ finished_pixel = (rgba) { MIN(source_pixel.red, dest_pixel.red),
815
+ MIN(source_pixel.green, dest_pixel.green),
816
+ MIN(source_pixel.blue, dest_pixel.blue),
817
+ MIN(source_pixel.alpha, dest_pixel.alpha) };
818
+ break;
819
+ case lighten:
820
+ finished_pixel = (rgba) { MAX(source_pixel.red, dest_pixel.red),
821
+ MAX(source_pixel.green, dest_pixel.green),
822
+ MAX(source_pixel.blue, dest_pixel.blue),
823
+ MAX(source_pixel.alpha, dest_pixel.alpha) };
824
+ break;
825
+ case colordodge:
826
+ finished_pixel = (rgba) { mode_colordodge_channel(dest_pixel.red, source_pixel.red),
827
+ mode_colordodge_channel(dest_pixel.green, source_pixel.green),
828
+ mode_colordodge_channel(dest_pixel.blue, source_pixel.blue),
829
+ mode_colordodge_channel(dest_pixel.alpha, source_pixel.alpha) };
830
+
831
+ break;
832
+ case colorburn:
833
+ finished_pixel = (rgba) { mode_colorburn_channel(dest_pixel.red, source_pixel.red),
834
+ mode_colorburn_channel(dest_pixel.green, source_pixel.green),
835
+ mode_colorburn_channel(dest_pixel.blue, source_pixel.blue),
836
+ mode_colorburn_channel(dest_pixel.alpha, source_pixel.alpha) };
837
+ break;
838
+ case hardlight:
839
+ finished_pixel = mode_hardlight(dest_pixel, source_pixel);
840
+
841
+ break;
842
+ case softlight:
843
+ finished_pixel = mode_softlight(dest_pixel, source_pixel);
844
+
845
+ break;
846
+ case difference:
847
+ finished_pixel = (rgba) { ABS(dest_pixel.red - source_pixel.red),
848
+ ABS(dest_pixel.green - source_pixel.green),
849
+ ABS(dest_pixel.blue - source_pixel.blue),
850
+ ABS(dest_pixel.alpha - source_pixel.alpha) };
851
+ break;
852
+ case exclusion:
853
+ finished_pixel = (rgba) { dest_pixel.red + source_pixel.red - (2 * dest_pixel.red * source_pixel.red),
854
+ dest_pixel.green + source_pixel.green - (2 * dest_pixel.green * source_pixel.green),
855
+ dest_pixel.blue + source_pixel.blue - (2 * dest_pixel.blue * source_pixel.blue),
856
+ dest_pixel.alpha + source_pixel.alpha - (2 * dest_pixel.alpha * source_pixel.alpha) };
857
+ break;
858
+ }
859
+
860
+ return finished_pixel;
861
+ }
862
+ /***************************************/
863
+ /**** end drawing mode related code ****/
864
+ /***************************************/
865
+
866
+
867
+ static rgba
868
+ apply_lerp(action_struct * payload, texture_info * tex, int x, int y)
869
+ {
870
+ rgba finished_pixel;
871
+ rgba dest_pixel = get_pixel_color(tex, x, y);
872
+
873
+ finished_pixel.red = payload->pen.lerp * payload->color.red +
874
+ (1 - payload->pen.lerp) * dest_pixel.red;
875
+
876
+ finished_pixel.green = payload->pen.lerp * payload->color.green +
877
+ (1 - payload->pen.lerp) * dest_pixel.green;
878
+
879
+ finished_pixel.blue = payload->pen.lerp * payload->color.blue +
880
+ (1 - payload->pen.lerp) * dest_pixel.blue;
881
+
882
+ finished_pixel.alpha = payload->pen.lerp * payload->color.alpha +
883
+ (1 - payload->pen.lerp) * dest_pixel.alpha;
884
+
885
+ return finished_pixel;
886
+ }
460
887
 
888
+
461
889
  /* TODO: reimplement using SSE2 */
462
890
  static rgba
463
891
  apply_color_control_transform(action_struct * payload, texture_info * tex, int x, int y)
@@ -40,6 +40,19 @@ typedef enum e_sync_mode {
40
40
  lazy_sync, eager_sync, no_sync
41
41
  } sync;
42
42
 
43
+ typedef enum {
44
+ clear, copy, noop,
45
+ set, copy_inverted,
46
+ invert, and_reverse, and,
47
+ or, nand, nor, xor,
48
+ equiv, and_inverted,
49
+ or_inverted, additive,
50
+ multiply, screen, overlay,
51
+ darken, lighten, colordodge,
52
+ colorburn, hardlight, softlight,
53
+ difference, exclusion
54
+ } draw_mode;
55
+
43
56
  /* structs */
44
57
  typedef struct s_rgba {
45
58
  float red, green, blue, alpha;
@@ -66,6 +79,7 @@ typedef struct {
66
79
  int ymax;
67
80
  } image_bounds;
68
81
 
82
+
69
83
  typedef struct action_struct {
70
84
  int xmin, ymin, xmax, ymax;
71
85
  sync sync_mode;
@@ -84,8 +98,8 @@ typedef struct action_struct {
84
98
  struct {
85
99
 
86
100
  /* color control, dynamic */
87
- VALUE color_control_proc;
88
101
  bool has_color_control_proc;
102
+ VALUE color_control_proc;
89
103
  int color_control_arity;
90
104
 
91
105
  /* color control, static */
@@ -94,11 +108,20 @@ typedef struct action_struct {
94
108
  rgba color_add;
95
109
 
96
110
  /* texture fill */
97
- texture_info source_tex;
98
111
  bool has_source_texture;
112
+ texture_info source_tex;
113
+
114
+ /* lerp */
115
+ bool has_lerp;
116
+ float lerp;
99
117
 
100
118
  /* alpha blend */
101
119
  bool alpha_blend;
120
+
121
+ /* drawing mode */
122
+ bool has_drawing_mode;
123
+ draw_mode drawing_mode;
124
+
102
125
  } pen;
103
126
 
104
127
  } action_struct;
@@ -727,9 +727,6 @@ fact(int n)
727
727
  unsigned
728
728
  comb(int n, int r)
729
729
  {
730
- /* double temp = fact(n) / (fact(r) * fact(n - r)); */
731
- /* return temp; */
732
-
733
730
  /* nCr is symmetrical about n / 2 */
734
731
  if(r > (n / 2))
735
732
  r = n - r;
@@ -1,3 +1,3 @@
1
- module TexPlay
2
- VERSION = "0.2.722"
3
- end
1
+ module TexPlay
2
+ VERSION = "0.2.800"
3
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 2
8
- - 722
9
- version: 0.2.722
8
+ - 800
9
+ version: 0.2.800
10
10
  platform: ruby
11
11
  authors:
12
12
  - John Mair (banisterfiend)
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-03-14 00:00:00 +13:00
17
+ date: 2010-03-22 00:00:00 +13:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -84,6 +84,7 @@ files:
84
84
  - examples/example_simple.rb
85
85
  - examples/example_splice.rb
86
86
  - examples/example_sync.rb
87
+ - examples/example_trace.rb
87
88
  - examples/example_turtle.rb
88
89
  - examples/example_weird.rb
89
90
  - examples/media/bird.png