texplay 0.2.722 → 0.2.800

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.
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