rays 0.1.25 → 0.1.28

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b6f7cc20d72750eb7d8ff9364831172720065e9f0339f0f865760c56b31e515b
4
- data.tar.gz: dd31681766629607b2fa461ae12d6904d325c0b8babba803faaf0443b0472242
3
+ metadata.gz: 38052c848aef75871de813ae9cc59a956672b1c6b8db25b55916f041ae0df976
4
+ data.tar.gz: d1f462fce0b73364a015fa1826eef17c3d1a4ac0b4378590f20438d87ce8e1cf
5
5
  SHA512:
6
- metadata.gz: f72e8c4cf249c3c7646a8d627e941dca67e7ac29a35d907e0c9ceac7522e3cdfd0df45e9eec8253a92fb70f031d53b5660eab594e50adfe6b8d12e4cb56b9a4e
7
- data.tar.gz: e7f4017fd414def3b492173e6a61f53a9fc2fef18dbe409eb7be6e27840ecbe2a26af60f62d7d507dc6ba12bd740e7606da2871ea218db1e5e5b116a242f8a84
6
+ metadata.gz: 9e01828d4ac2ad4749a9d050d3890669be7e35dd057cc92b0dae23f645954b44bf7f3775d193ef36d9590d10879175a7937b28ceddf0bf9fd29a84723f0cfdbe
7
+ data.tar.gz: da8b670d9e704d4cc48070d5d252ec504e433f00222160a5c42ccf7a036eabc1a31580b6318da59672bc8576b0dddf84fce635ce9194f4a462eebfc8d4e03451
@@ -26,15 +26,51 @@ VALUE alloc(VALUE klass)
26
26
  }
27
27
 
28
28
  static
29
- VALUE canvas(VALUE self, VALUE x, VALUE y, VALUE width, VALUE height)
29
+ VALUE canvas(VALUE self)
30
30
  {
31
31
  CHECK;
32
+ check_arg_count(__FILE__, __LINE__, "Painter#canvas", argc, 4, 5, 6, 7);
32
33
 
33
- coord xx = to<coord>(x);
34
- coord yy = to<coord>(y);
35
- coord ww = to<coord>(width);
36
- coord hh = to<coord>(height);
37
- THIS->canvas(xx, yy, ww, hh);
34
+ switch (argc)
35
+ {
36
+ case 4:
37
+ THIS->canvas(
38
+ to<coord>(argv[0]),
39
+ to<coord>(argv[1]),
40
+ to<coord>(argv[2]),
41
+ to<coord>(argv[3]));
42
+ break;
43
+
44
+ case 5:
45
+ THIS->canvas(
46
+ to<coord>(argv[0]),
47
+ to<coord>(argv[1]),
48
+ to<coord>(argv[2]),
49
+ to<coord>(argv[3]),
50
+ to<float>(argv[4]));
51
+ break;
52
+
53
+ case 6:
54
+ THIS->canvas(
55
+ to<coord>(argv[0]),
56
+ to<coord>(argv[1]),
57
+ to<coord>(argv[2]),
58
+ to<coord>(argv[3]),
59
+ to<coord>(argv[4]),
60
+ to<coord>(argv[5]));
61
+ break;
62
+
63
+ case 7:
64
+ THIS->canvas(
65
+ to<coord>(argv[0]),
66
+ to<coord>(argv[1]),
67
+ to<coord>(argv[2]),
68
+ to<coord>(argv[3]),
69
+ to<coord>(argv[4]),
70
+ to<coord>(argv[5]),
71
+ to<float>(argv[6]));
72
+ break;
73
+ }
38
74
 
39
75
  return self;
40
76
  }
@@ -382,6 +418,21 @@ VALUE get_nsegment(VALUE self)
382
418
  return value(THIS->nsegment());
383
419
  }
384
420
 
421
+ static
422
+ VALUE set_blend_mode(VALUE self, VALUE mode)
423
+ {
424
+ CHECK;
425
+ THIS->set_blend_mode(to<Rays::BlendMode>(mode));
426
+ return self;
427
+ }
428
+
429
+ static
430
+ VALUE get_blend_mode(VALUE self)
431
+ {
432
+ CHECK;
433
+ return value(THIS->blend_mode());
434
+ }
435
+
385
436
  static
386
437
  VALUE set_clip(VALUE self)
387
438
  {
@@ -428,7 +479,10 @@ VALUE set_shader(VALUE self)
428
479
  CHECK;
429
480
  check_arg_count(__FILE__, __LINE__, "Painter#set_shader", argc, 1);
430
481
 
431
- THIS->set_shader(to<Rays::Shader>(argc, argv));
482
+ if (argc >= 1 && !argv[0])
483
+ THIS->no_shader();
484
+ else
485
+ THIS->set_shader(to<Rays::Shader>(argc, argv));
432
486
  return self;
433
487
  }
434
488
 
@@ -436,7 +490,9 @@ static
436
490
  VALUE get_shader(VALUE self)
437
491
  {
438
492
  CHECK;
439
- return value(THIS->shader());
493
+
494
+ const Rays::Shader& shader = THIS->shader();
495
+ return shader ? value(shader) : nil();
440
496
  }
441
497
 
442
498
  static
@@ -553,7 +609,7 @@ Init_painter ()
553
609
  cPainter = rb_define_class_under(mRays, "Painter", rb_cObject);
554
610
  rb_define_alloc_func(cPainter, alloc);
555
611
 
556
- rb_define_method(cPainter, "canvas", RUBY_METHOD_FUNC(canvas), 4);
612
+ rb_define_method(cPainter, "canvas", RUBY_METHOD_FUNC(canvas), -1);
557
613
  rb_define_method(cPainter, "bounds", RUBY_METHOD_FUNC(bounds), 0);
558
614
  rb_define_method(cPainter, "pixel_density", RUBY_METHOD_FUNC(pixel_density), 0);
559
615
 
@@ -589,6 +645,8 @@ Init_painter ()
589
645
  rb_define_method(cPainter, "miter_limit", RUBY_METHOD_FUNC(get_miter_limit), 0);
590
646
  rb_define_method(cPainter, "nsegment=", RUBY_METHOD_FUNC(set_nsegment), 1);
591
647
  rb_define_method(cPainter, "nsegment", RUBY_METHOD_FUNC(get_nsegment), 0);
648
+ rb_define_method(cPainter, "blend_mode=", RUBY_METHOD_FUNC(set_blend_mode), 1);
649
+ rb_define_method(cPainter, "blend_mode", RUBY_METHOD_FUNC(get_blend_mode), 0);
592
650
  rb_define_method(cPainter, "clip=", RUBY_METHOD_FUNC(set_clip), -1);
593
651
  rb_define_method(cPainter, "clip", RUBY_METHOD_FUNC(get_clip), 0);
594
652
  rb_define_method(cPainter, "no_clip", RUBY_METHOD_FUNC(no_clip), 0);
@@ -7,6 +7,7 @@
7
7
 
8
8
  RUCY_DEFINE_CONVERT_TO(Rays::CapType)
9
9
  RUCY_DEFINE_CONVERT_TO(Rays::JoinType)
10
+ RUCY_DEFINE_CONVERT_TO(Rays::BlendMode)
10
11
 
11
12
 
12
13
  template <typename T>
@@ -29,6 +30,18 @@ static std::vector<EnumType<Rays::JoinType>> JOIN_TYPES({
29
30
  {"JOIN_SQUARE", "SQUARE", Rays::JOIN_SQUARE},
30
31
  });
31
32
 
33
+ static std::vector<EnumType<Rays::BlendMode>> BLEND_MODES({
34
+ {"BLEND_NORMAL", "NORMAL", Rays::BLEND_NORMAL},
35
+ {"BLEND_ADD", "ADD", Rays::BLEND_ADD},
36
+ {"BLEND_SUBTRACT", "SUBTRACT", Rays::BLEND_SUBTRACT},
37
+ {"BLEND_LIGHTEST", "LIGHTEST", Rays::BLEND_LIGHTEST},
38
+ {"BLEND_DARKEST", "DARKEST", Rays::BLEND_DARKEST},
39
+ {"BLEND_EXCLUSION", "EXCLUSION", Rays::BLEND_EXCLUSION},
40
+ {"BLEND_MULTIPLY", "MULTIPLY", Rays::BLEND_MULTIPLY},
41
+ {"BLEND_SCREEN", "SCREEN", Rays::BLEND_SCREEN},
42
+ {"BLEND_REPLACE", "REPLACE", Rays::BLEND_REPLACE},
43
+ });
44
+
32
45
 
33
46
  static
34
47
  VALUE init(VALUE self)
@@ -60,6 +73,9 @@ Init_rays ()
60
73
 
61
74
  for (auto it = JOIN_TYPES.begin(); it != JOIN_TYPES.end(); ++it)
62
75
  mRays.define_const(it->name, it->type);
76
+
77
+ for (auto it = BLEND_MODES.begin(); it != BLEND_MODES.end(); ++it)
78
+ mRays.define_const(it->name, it->type);
63
79
  }
64
80
 
65
81
 
@@ -129,6 +145,37 @@ namespace Rucy
129
145
  }
130
146
 
131
147
 
148
+ template <> Rays::BlendMode
149
+ value_to<Rays::BlendMode> (int argc, const Value* argv, bool convert)
150
+ {
151
+ assert(argc > 0 && argv);
152
+
153
+ if (convert)
154
+ {
155
+ if (argv->is_s() || argv->is_sym())
156
+ {
157
+ const char* str = argv->c_str();
158
+ for (auto it = BLEND_MODES.begin(); it != BLEND_MODES.end(); ++it)
159
+ {
160
+ if (
161
+ strcasecmp(str, it->name) == 0 ||
162
+ strcasecmp(str, it->short_name) == 0)
163
+ {
164
+ return it->type;
165
+ }
166
+ }
167
+ argument_error(__FILE__, __LINE__, "invalid blend mode -- %s", str);
168
+ }
169
+ }
170
+
171
+ int type = value_to<int>(*argv, convert);
172
+ if (type < 0 || Rays::BLEND_MAX <= type)
173
+ argument_error(__FILE__, __LINE__, "invalid blend mode -- %d", type);
174
+
175
+ return (Rays::BlendMode) type;
176
+ }
177
+
178
+
132
179
  }// Rucy
133
180
 
134
181
 
data/Rakefile CHANGED
@@ -38,4 +38,4 @@ test_ruby_extension
38
38
  generate_documents
39
39
  build_ruby_gem
40
40
 
41
- task :default => :test
41
+ task :default => :ext
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.25
1
+ 0.1.28
data/ext/rays/painter.cpp CHANGED
@@ -27,15 +27,51 @@ RUCY_DEF_ALLOC(alloc, klass)
27
27
  RUCY_END
28
28
 
29
29
  static
30
- RUCY_DEF4(canvas, x, y, width, height)
30
+ RUCY_DEFN(canvas)
31
31
  {
32
32
  CHECK;
33
+ check_arg_count(__FILE__, __LINE__, "Painter#canvas", argc, 4, 5, 6, 7);
33
34
 
34
- coord xx = to<coord>(x);
35
- coord yy = to<coord>(y);
36
- coord ww = to<coord>(width);
37
- coord hh = to<coord>(height);
38
- THIS->canvas(xx, yy, ww, hh);
35
+ switch (argc)
36
+ {
37
+ case 4:
38
+ THIS->canvas(
39
+ to<coord>(argv[0]),
40
+ to<coord>(argv[1]),
41
+ to<coord>(argv[2]),
42
+ to<coord>(argv[3]));
43
+ break;
44
+
45
+ case 5:
46
+ THIS->canvas(
47
+ to<coord>(argv[0]),
48
+ to<coord>(argv[1]),
49
+ to<coord>(argv[2]),
50
+ to<coord>(argv[3]),
51
+ to<float>(argv[4]));
52
+ break;
53
+
54
+ case 6:
55
+ THIS->canvas(
56
+ to<coord>(argv[0]),
57
+ to<coord>(argv[1]),
58
+ to<coord>(argv[2]),
59
+ to<coord>(argv[3]),
60
+ to<coord>(argv[4]),
61
+ to<coord>(argv[5]));
62
+ break;
63
+
64
+ case 7:
65
+ THIS->canvas(
66
+ to<coord>(argv[0]),
67
+ to<coord>(argv[1]),
68
+ to<coord>(argv[2]),
69
+ to<coord>(argv[3]),
70
+ to<coord>(argv[4]),
71
+ to<coord>(argv[5]),
72
+ to<float>(argv[6]));
73
+ break;
74
+ }
39
75
 
40
76
  return self;
41
77
  }
@@ -417,6 +453,23 @@ RUCY_DEF0(get_nsegment)
417
453
  }
418
454
  RUCY_END
419
455
 
456
+ static
457
+ RUCY_DEF1(set_blend_mode, mode)
458
+ {
459
+ CHECK;
460
+ THIS->set_blend_mode(to<Rays::BlendMode>(mode));
461
+ return self;
462
+ }
463
+ RUCY_END
464
+
465
+ static
466
+ RUCY_DEF0(get_blend_mode)
467
+ {
468
+ CHECK;
469
+ return value(THIS->blend_mode());
470
+ }
471
+ RUCY_END
472
+
420
473
  static
421
474
  RUCY_DEFN(set_clip)
422
475
  {
@@ -468,7 +521,10 @@ RUCY_DEFN(set_shader)
468
521
  CHECK;
469
522
  check_arg_count(__FILE__, __LINE__, "Painter#set_shader", argc, 1);
470
523
 
471
- THIS->set_shader(to<Rays::Shader>(argc, argv));
524
+ if (argc >= 1 && !argv[0])
525
+ THIS->no_shader();
526
+ else
527
+ THIS->set_shader(to<Rays::Shader>(argc, argv));
472
528
  return self;
473
529
  }
474
530
  RUCY_END
@@ -477,7 +533,9 @@ static
477
533
  RUCY_DEF0(get_shader)
478
534
  {
479
535
  CHECK;
480
- return value(THIS->shader());
536
+
537
+ const Rays::Shader& shader = THIS->shader();
538
+ return shader ? value(shader) : nil();
481
539
  }
482
540
  RUCY_END
483
541
 
@@ -641,6 +699,8 @@ Init_painter ()
641
699
  cPainter.define_method("miter_limit", get_miter_limit);
642
700
  cPainter.define_method("nsegment=", set_nsegment);
643
701
  cPainter.define_method("nsegment", get_nsegment);
702
+ cPainter.define_method("blend_mode=", set_blend_mode);
703
+ cPainter.define_method("blend_mode", get_blend_mode);
644
704
  cPainter.define_method( "clip=", set_clip);
645
705
  cPainter.define_method( "clip", get_clip);
646
706
  cPainter.define_method("no_clip", no_clip);
data/ext/rays/rays.cpp CHANGED
@@ -7,6 +7,7 @@
7
7
 
8
8
  RUCY_DEFINE_CONVERT_TO(Rays::CapType)
9
9
  RUCY_DEFINE_CONVERT_TO(Rays::JoinType)
10
+ RUCY_DEFINE_CONVERT_TO(Rays::BlendMode)
10
11
 
11
12
 
12
13
  template <typename T>
@@ -29,6 +30,18 @@ static std::vector<EnumType<Rays::JoinType>> JOIN_TYPES({
29
30
  {"JOIN_SQUARE", "SQUARE", Rays::JOIN_SQUARE},
30
31
  });
31
32
 
33
+ static std::vector<EnumType<Rays::BlendMode>> BLEND_MODES({
34
+ {"BLEND_NORMAL", "NORMAL", Rays::BLEND_NORMAL},
35
+ {"BLEND_ADD", "ADD", Rays::BLEND_ADD},
36
+ {"BLEND_SUBTRACT", "SUBTRACT", Rays::BLEND_SUBTRACT},
37
+ {"BLEND_LIGHTEST", "LIGHTEST", Rays::BLEND_LIGHTEST},
38
+ {"BLEND_DARKEST", "DARKEST", Rays::BLEND_DARKEST},
39
+ {"BLEND_EXCLUSION", "EXCLUSION", Rays::BLEND_EXCLUSION},
40
+ {"BLEND_MULTIPLY", "MULTIPLY", Rays::BLEND_MULTIPLY},
41
+ {"BLEND_SCREEN", "SCREEN", Rays::BLEND_SCREEN},
42
+ {"BLEND_REPLACE", "REPLACE", Rays::BLEND_REPLACE},
43
+ });
44
+
32
45
 
33
46
  static
34
47
  RUCY_DEF0(init)
@@ -62,6 +75,9 @@ Init_rays ()
62
75
 
63
76
  for (auto it = JOIN_TYPES.begin(); it != JOIN_TYPES.end(); ++it)
64
77
  mRays.define_const(it->name, it->type);
78
+
79
+ for (auto it = BLEND_MODES.begin(); it != BLEND_MODES.end(); ++it)
80
+ mRays.define_const(it->name, it->type);
65
81
  }
66
82
 
67
83
 
@@ -131,6 +147,37 @@ namespace Rucy
131
147
  }
132
148
 
133
149
 
150
+ template <> Rays::BlendMode
151
+ value_to<Rays::BlendMode> (int argc, const Value* argv, bool convert)
152
+ {
153
+ assert(argc > 0 && argv);
154
+
155
+ if (convert)
156
+ {
157
+ if (argv->is_s() || argv->is_sym())
158
+ {
159
+ const char* str = argv->c_str();
160
+ for (auto it = BLEND_MODES.begin(); it != BLEND_MODES.end(); ++it)
161
+ {
162
+ if (
163
+ strcasecmp(str, it->name) == 0 ||
164
+ strcasecmp(str, it->short_name) == 0)
165
+ {
166
+ return it->type;
167
+ }
168
+ }
169
+ argument_error(__FILE__, __LINE__, "invalid blend mode -- %s", str);
170
+ }
171
+ }
172
+
173
+ int type = value_to<int>(*argv, convert);
174
+ if (type < 0 || Rays::BLEND_MAX <= type)
175
+ argument_error(__FILE__, __LINE__, "invalid blend mode -- %d", type);
176
+
177
+ return (Rays::BlendMode) type;
178
+ }
179
+
180
+
134
181
  }// Rucy
135
182
 
136
183
 
data/include/rays/defs.h CHANGED
@@ -56,6 +56,32 @@ namespace Rays
56
56
  };// JoinType
57
57
 
58
58
 
59
+ enum BlendMode
60
+ {
61
+
62
+ BLEND_NORMAL = 0,
63
+
64
+ BLEND_ADD,
65
+
66
+ BLEND_SUBTRACT,
67
+
68
+ BLEND_LIGHTEST,
69
+
70
+ BLEND_DARKEST,
71
+
72
+ BLEND_EXCLUSION,
73
+
74
+ BLEND_MULTIPLY,
75
+
76
+ BLEND_SCREEN,
77
+
78
+ BLEND_REPLACE,
79
+
80
+ BLEND_MAX
81
+
82
+ };// BlendMode
83
+
84
+
59
85
  }// Rays
60
86
 
61
87
 
@@ -174,7 +174,8 @@ namespace Rays
174
174
  //
175
175
  // states
176
176
  //
177
- void set_background (float red, float green, float blue, float alpha = 1, bool clear = true);
177
+ void set_background (
178
+ float red, float green, float blue, float alpha = 1, bool clear = true);
178
179
 
179
180
  void set_background (const Color& color, bool clear = true);
180
181
 
@@ -218,6 +219,10 @@ namespace Rays
218
219
 
219
220
  uint nsegment () const;
220
221
 
222
+ void set_blend_mode (BlendMode mode);
223
+
224
+ BlendMode blend_mode () const;
225
+
221
226
  void set_clip (coord x, coord y, coord width, coord height);
222
227
 
223
228
  void set_clip (const Bounds& bounds);
@@ -25,5 +25,7 @@ RUCY_DECLARE_CONVERT_TO(Rays::CapType)
25
25
 
26
26
  RUCY_DECLARE_CONVERT_TO(Rays::JoinType)
27
27
 
28
+ RUCY_DECLARE_CONVERT_TO(Rays::BlendMode)
29
+
28
30
 
29
31
  #endif//EOH
data/lib/rays/painter.rb CHANGED
@@ -108,9 +108,21 @@ module Rays
108
108
  square: JOIN_SQUARE
109
109
  }
110
110
 
111
+ const_symbol_accessor :blend_mode, **{
112
+ normal: BLEND_NORMAL,
113
+ add: BLEND_ADD,
114
+ subtract: BLEND_SUBTRACT,
115
+ lightest: BLEND_LIGHTEST,
116
+ darkest: BLEND_DARKEST,
117
+ exclusion: BLEND_EXCLUSION,
118
+ multiply: BLEND_MULTIPLY,
119
+ screen: BLEND_SCREEN,
120
+ replace: BLEND_REPLACE
121
+ }
122
+
111
123
  universal_accessor :background, :fill, :stroke, :color,
112
124
  :stroke_width, :stroke_cap, :stroke_join, :miter_limit,
113
- :nsegment, :shader, :clip, :font
125
+ :nsegment, :blend_mode, :shader, :clip, :font
114
126
 
115
127
  private
116
128
 
data/rays.gemspec CHANGED
@@ -28,8 +28,8 @@ Gem::Specification.new do |s|
28
28
  s.platform = Gem::Platform::RUBY
29
29
  s.required_ruby_version = '>= 2.6.0'
30
30
 
31
- s.add_runtime_dependency 'xot', '~> 0.1.25'
32
- s.add_runtime_dependency 'rucy', '~> 0.1.25'
31
+ s.add_runtime_dependency 'xot', '~> 0.1.28'
32
+ s.add_runtime_dependency 'rucy', '~> 0.1.28'
33
33
 
34
34
  s.files = `git ls-files`.split $/
35
35
  s.executables = s.files.grep(%r{^bin/}) {|f| File.basename f}
data/src/frame_buffer.cpp CHANGED
@@ -110,7 +110,7 @@ namespace Rays
110
110
 
111
111
  self->texture = texture;
112
112
 
113
- #if 0
113
+ #if 1
114
114
  int w = texture.reserved_width(), h = texture.reserved_height();
115
115
  if (
116
116
  w != self->render_buffer.width() ||
@@ -119,8 +119,7 @@ namespace Rays
119
119
  RenderBuffer rb = RenderBuffer(w, h);
120
120
 
121
121
  glFramebufferRenderbuffer(
122
- GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
123
- GL_RENDERBUFFER, rb.id());
122
+ GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb.id());
124
123
  OpenGL_check_error(__FILE__, __LINE__);
125
124
 
126
125
  self->render_buffer = rb;
data/src/ios/bitmap.mm CHANGED
@@ -224,9 +224,26 @@ namespace Rays
224
224
  return bitmap.self->modified;
225
225
  }
226
226
 
227
+ static CFStringRef
228
+ get_bitmap_type (const char* path_)
229
+ {
230
+ String path = path_;
231
+ path = path.downcase();
232
+ if (path.ends_with(".png")) return kUTTypePNG;
233
+ if (path.ends_with(".gif")) return kUTTypeGIF;
234
+ if (path.ends_with(".bmp")) return kUTTypeBMP;
235
+ if (path.ends_with(".jpg") || path.ends_with(".jpeg")) return kUTTypeJPEG;
236
+ if (path.ends_with(".tif") || path.ends_with(".tiff")) return kUTTypeTIFF;
237
+ return nil;
238
+ }
239
+
227
240
  void
228
241
  Bitmap_save (const Bitmap& bmp, const char* path_)
229
242
  {
243
+ const CFStringRef type = get_bitmap_type(path_);
244
+ if (!type)
245
+ argument_error(__FILE__, __LINE__, "unknown image file type");
246
+
230
247
  std::shared_ptr<CGImage> img(bmp.self->get_image(), CGImageRelease);
231
248
  if (!img)
232
249
  rays_error(__FILE__, __LINE__, "getting CGImage failed.");
@@ -237,7 +254,7 @@ namespace Rays
237
254
  rays_error(__FILE__, __LINE__, "creating NSURL failed.");
238
255
 
239
256
  std::shared_ptr<CGImageDestination> dest(
240
- CGImageDestinationCreateWithURL((CFURLRef) url, kUTTypePNG, 1, NULL),
257
+ CGImageDestinationCreateWithURL((CFURLRef) url, type, 1, NULL),
241
258
  safe_cfrelease);
242
259
  if (!dest)
243
260
  rays_error(__FILE__, __LINE__, "CGImageDestinationCreateWithURL() failed.");
data/src/osx/bitmap.mm CHANGED
@@ -223,9 +223,26 @@ namespace Rays
223
223
  return bitmap.self->modified;
224
224
  }
225
225
 
226
+ static CFStringRef
227
+ get_bitmap_type (const char* path_)
228
+ {
229
+ String path = path_;
230
+ path = path.downcase();
231
+ if (path.ends_with(".png")) return kUTTypePNG;
232
+ if (path.ends_with(".gif")) return kUTTypeGIF;
233
+ if (path.ends_with(".bmp")) return kUTTypeBMP;
234
+ if (path.ends_with(".jpg") || path.ends_with(".jpeg")) return kUTTypeJPEG;
235
+ if (path.ends_with(".tif") || path.ends_with(".tiff")) return kUTTypeTIFF;
236
+ return nil;
237
+ }
238
+
226
239
  void
227
240
  Bitmap_save (const Bitmap& bmp, const char* path_)
228
241
  {
242
+ const CFStringRef type = get_bitmap_type(path_);
243
+ if (!type)
244
+ argument_error(__FILE__, __LINE__, "unknown image file type");
245
+
229
246
  std::shared_ptr<CGImage> img(bmp.self->get_image(), CGImageRelease);
230
247
  if (!img)
231
248
  rays_error(__FILE__, __LINE__, "getting CGImage failed.");
@@ -236,7 +253,7 @@ namespace Rays
236
253
  rays_error(__FILE__, __LINE__, "creating NSURL failed.");
237
254
 
238
255
  std::shared_ptr<CGImageDestination> dest(
239
- CGImageDestinationCreateWithURL((CFURLRef) url, kUTTypePNG, 1, NULL),
256
+ CGImageDestinationCreateWithURL((CFURLRef) url, type, 1, NULL),
240
257
  safe_cfrelease);
241
258
  if (!dest)
242
259
  rays_error(__FILE__, __LINE__, "CGImageDestinationCreateWithURL() failed.");
data/src/painter.cpp CHANGED
@@ -56,6 +56,8 @@ namespace Rays
56
56
 
57
57
  uint nsegment;
58
58
 
59
+ BlendMode blend_mode;
60
+
59
61
  Bounds clip;
60
62
 
61
63
  Font font;
@@ -72,6 +74,7 @@ namespace Rays
72
74
  stroke_join = JOIN_DEFAULT;
73
75
  miter_limit = JOIN_DEFAULT_MITER_LIMIT;
74
76
  nsegment = 0;
77
+ blend_mode = BLEND_NORMAL;
75
78
  clip .reset(-1);
76
79
  font = default_font();
77
80
  shader = Shader();
@@ -107,7 +110,7 @@ namespace Rays
107
110
  return
108
111
  texture &&
109
112
  texcoord_min.x < texcoord_max.x &&
110
- texcoord_min.x < texcoord_max.y;
113
+ texcoord_min.y < texcoord_max.y;
111
114
  }
112
115
 
113
116
  bool operator ! () const
@@ -125,10 +128,14 @@ namespace Rays
125
128
 
126
129
  GLclampf color_clear[4];
127
130
 
131
+ GLboolean depth_test;
132
+ GLint depth_func;
133
+
128
134
  GLboolean scissor_test;
129
135
  GLint scissor_box[4];
130
136
 
131
137
  GLboolean blend;
138
+ GLint blend_equation_rgb, blend_equation_alpha;
132
139
  GLint blend_src_rgb, blend_src_alpha, blend_dst_rgb, blend_dst_alpha;
133
140
 
134
141
  GLint framebuffer_binding;
@@ -139,10 +146,15 @@ namespace Rays
139
146
 
140
147
  glGetFloatv(GL_COLOR_CLEAR_VALUE, color_clear);
141
148
 
149
+ glGetBooleanv(GL_DEPTH_TEST, &depth_test);
150
+ glGetIntegerv(GL_DEPTH_FUNC, &depth_func);
151
+
142
152
  glGetBooleanv(GL_SCISSOR_TEST, &scissor_test);
143
153
  glGetIntegerv(GL_SCISSOR_BOX, scissor_box);
144
154
 
145
155
  glGetBooleanv(GL_BLEND, &blend);
156
+ glGetIntegerv(GL_BLEND_EQUATION_RGB, &blend_equation_rgb);
157
+ glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blend_equation_alpha);
146
158
  glGetIntegerv(GL_BLEND_SRC_RGB, &blend_src_rgb);
147
159
  glGetIntegerv(GL_BLEND_SRC_ALPHA, &blend_src_alpha);
148
160
  glGetIntegerv(GL_BLEND_DST_RGB, &blend_dst_rgb);
@@ -158,10 +170,14 @@ namespace Rays
158
170
  glClearColor(
159
171
  color_clear[0], color_clear[1], color_clear[2], color_clear[3]);
160
172
 
173
+ enable(GL_DEPTH_TEST, depth_test);
174
+ glDepthFunc(depth_func);
175
+
161
176
  enable(GL_SCISSOR_TEST, scissor_test);
162
177
  glScissor(scissor_box[0], scissor_box[1], scissor_box[2], scissor_box[3]);
163
178
 
164
179
  enable(GL_BLEND, blend);
180
+ glBlendEquationSeparate(blend_equation_rgb, blend_equation_alpha);
165
181
  glBlendFuncSeparate(
166
182
  blend_src_rgb, blend_dst_rgb, blend_src_alpha, blend_dst_alpha);
167
183
 
@@ -566,7 +582,7 @@ namespace Rays
566
582
  Painter::canvas (
567
583
  coord x, coord y, coord width, coord height, float pixel_density)
568
584
  {
569
- canvas(Bounds(x, y, -100, width, height, 200), pixel_density);
585
+ canvas(x, y, 0, width, height, 0, pixel_density);
570
586
  }
571
587
 
572
588
  void
@@ -639,10 +655,14 @@ namespace Rays
639
655
  self->opengl_state.push();
640
656
 
641
657
  //glEnable(GL_CULL_FACE);
642
- glEnable(GL_BLEND);
643
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
658
+
659
+ glEnable(GL_DEPTH_TEST);
660
+ glDepthFunc(GL_LEQUAL);
644
661
  OpenGL_check_error(__FILE__, __LINE__);
645
662
 
663
+ glEnable(GL_BLEND);
664
+ set_blend_mode(self->state.blend_mode);
665
+
646
666
  FrameBuffer& fb = self->frame_buffer;
647
667
  if (fb) FrameBuffer_bind(fb.id());
648
668
 
@@ -656,16 +676,23 @@ namespace Rays
656
676
  coord x1 = vp.x, x2 = vp.x + vp.width;
657
677
  coord y1 = vp.y, y2 = vp.y + vp.height;
658
678
  coord z1 = vp.z, z2 = vp.z + vp.depth;
659
- if (z1 == 0 && z2 == 0) {z1 = -100; z2 = 200;}
679
+ if (z1 == 0 && z2 == 0) {z1 = -1000; z2 = 1000;}
660
680
  if (!fb) std::swap(y1, y2);
661
681
 
662
682
  self->position_matrix.reset(1);
663
683
  self->position_matrix *= to_rays(glm::ortho(x1, x2, y1, y2));
684
+
685
+ // map z to 0.0-1.0
686
+ self->position_matrix.scale(1, 1, 1.0 / (z2 - z1));
687
+ self->position_matrix.translate(0, 0, -z2);
688
+
664
689
  //self->position_matrix.translate(0.375f, 0.375f);
665
690
 
666
691
  self->update_clip();
667
692
 
668
693
  self->painting = true;
694
+
695
+ glClear(GL_DEPTH_BUFFER_BIT);
669
696
  }
670
697
 
671
698
  void
@@ -703,7 +730,7 @@ namespace Rays
703
730
 
704
731
  const Color& c = self->state.background;
705
732
  glClearColor(c.red, c.green, c.blue, c.alpha);
706
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
733
+ glClear(GL_COLOR_BUFFER_BIT);
707
734
  OpenGL_check_error(__FILE__, __LINE__);
708
735
  }
709
736
 
@@ -1293,6 +1320,72 @@ namespace Rays
1293
1320
  return self->state.nsegment;
1294
1321
  }
1295
1322
 
1323
+ void
1324
+ Painter::set_blend_mode (BlendMode mode)
1325
+ {
1326
+ self->state.blend_mode = mode;
1327
+ switch (mode)
1328
+ {
1329
+ case BLEND_NORMAL:
1330
+ glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
1331
+ glBlendFuncSeparate(
1332
+ GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
1333
+ break;
1334
+
1335
+ case BLEND_ADD:
1336
+ glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
1337
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE);
1338
+ break;
1339
+
1340
+ case BLEND_SUBTRACT:
1341
+ glBlendEquationSeparate(GL_FUNC_REVERSE_SUBTRACT, GL_FUNC_ADD);
1342
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE);
1343
+ break;
1344
+
1345
+ case BLEND_LIGHTEST:
1346
+ glBlendEquationSeparate(GL_MAX, GL_FUNC_ADD);
1347
+ glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
1348
+ break;
1349
+
1350
+ case BLEND_DARKEST:
1351
+ glBlendEquationSeparate(GL_MIN, GL_FUNC_ADD);
1352
+ glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
1353
+ break;
1354
+
1355
+ case BLEND_EXCLUSION:
1356
+ glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
1357
+ glBlendFuncSeparate(
1358
+ GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_ONE, GL_ONE);
1359
+ break;
1360
+
1361
+ case BLEND_MULTIPLY:
1362
+ glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
1363
+ glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ONE, GL_ONE);
1364
+ break;
1365
+
1366
+ case BLEND_SCREEN:
1367
+ glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
1368
+ glBlendFuncSeparate(GL_ONE_MINUS_DST_COLOR, GL_ONE, GL_ONE, GL_ONE);
1369
+ break;
1370
+
1371
+ case BLEND_REPLACE:
1372
+ glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
1373
+ glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO);
1374
+ break;
1375
+
1376
+ default:
1377
+ argument_error(__FILE__, __LINE__, "unknown blend mode");
1378
+ break;
1379
+ }
1380
+ OpenGL_check_error(__FILE__, __LINE__);
1381
+ }
1382
+
1383
+ BlendMode
1384
+ Painter::blend_mode () const
1385
+ {
1386
+ return self->state.blend_mode;
1387
+ }
1388
+
1296
1389
  void
1297
1390
  Painter::set_clip (coord x, coord y, coord width, coord height)
1298
1391
  {
@@ -1318,9 +1411,19 @@ namespace Rays
1318
1411
  return self->state.clip;
1319
1412
  }
1320
1413
 
1414
+ static bool
1415
+ has_same_font (const Font& font, const char* name, coord size)
1416
+ {
1417
+ return
1418
+ font.size() == size &&
1419
+ font.name() == (name ? name : default_font().name().c_str());
1420
+ }
1421
+
1321
1422
  void
1322
1423
  Painter::set_font (const char* name, coord size)
1323
1424
  {
1425
+ if (has_same_font(self->state.font, name, size)) return;
1426
+
1324
1427
  set_font(Font(name, size));
1325
1428
  }
1326
1429
 
@@ -54,8 +54,11 @@ namespace Rays
54
54
  #else
55
55
  GL_DEPTH_COMPONENT24,
56
56
  #endif
57
- width,
58
- height);
57
+ width_,
58
+ height_);
59
+ OpenGL_check_error(__FILE__, __LINE__);
60
+
61
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
59
62
  OpenGL_check_error(__FILE__, __LINE__);
60
63
 
61
64
  width = width_;
data/test/test_image.rb CHANGED
@@ -6,11 +6,12 @@ require_relative 'helper'
6
6
 
7
7
  class TestImage < Test::Unit::TestCase
8
8
 
9
- W = 10
10
- H = 10
9
+ def image(*args)
10
+ Rays::Image.new(*args)
11
+ end
11
12
 
12
- def image(w = W, h = H, *args)
13
- Rays::Image.new w, h, *args
13
+ def load(path)
14
+ Rays::Image.load path
14
15
  end
15
16
 
16
17
  def color(r = 0, g = 0, b = 0, a = 0)
@@ -22,12 +23,12 @@ class TestImage < Test::Unit::TestCase
22
23
  end
23
24
 
24
25
  def test_initialize()
25
- assert_equal W, image.width
26
- assert_equal H, image.height
26
+ assert_equal 10, image(10, 20).width
27
+ assert_equal 10, image(20, 10).height
27
28
  end
28
29
 
29
30
  def test_dup()
30
- o = image
31
+ o = image 10, 10
31
32
  assert_equal color(0, 0, 0, 0), o[0, 0]
32
33
  o[0, 0] = color(1, 0, 0, 0)
33
34
  assert_equal color(1, 0, 0, 0), o[0, 0]
@@ -39,12 +40,12 @@ class TestImage < Test::Unit::TestCase
39
40
  end
40
41
 
41
42
  def test_bitmap()
42
- assert_equal W, image.bitmap.width
43
- assert_equal H, image.bitmap.height
43
+ assert_equal 10, image(10, 20).bitmap.width
44
+ assert_equal 10, image(20, 10).bitmap.height
44
45
  end
45
46
 
46
47
  def test_painter()
47
- pa = image.painter
48
+ pa = image(10, 10).painter
48
49
  assert_equal color(0, 0, 0, 0), pa.background
49
50
  assert_equal color(1, 1, 1, 1), pa.fill
50
51
  assert_equal color(1, 1, 1, 0), pa.stroke
@@ -73,4 +74,38 @@ class TestImage < Test::Unit::TestCase
73
74
  assert drawn {|p| p.text "a"}
74
75
  end
75
76
 
77
+ def test_save_load()
78
+ def get_image_type(filename)
79
+ `file #{filename}`.match(/#{filename}: ([^,]+),/)[1]
80
+ end
81
+
82
+ img = image(10, 10).paint {fill 1, 0, 0; ellipse 0, 0, 10}
83
+ pixels = img.bitmap.to_a
84
+ paths = %w[png jpg jpeg gif bmp tif tiff].map {|ext| "#{__dir__}/testimage.#{ext}"}
85
+
86
+ png, jpg, jpeg, gif, bmp, tif, tiff = paths
87
+
88
+ paths.each {|path| img.save path}
89
+
90
+ assert_equal 'PNG image data', get_image_type(png)
91
+ assert_equal 'JPEG image data', get_image_type(jpg)
92
+ assert_equal 'JPEG image data', get_image_type(jpeg)
93
+ assert_equal 'GIF image data', get_image_type(gif)
94
+ assert_equal 'PC bitmap', get_image_type(bmp)
95
+ assert_equal 'TIFF image data', get_image_type(tif)
96
+ assert_equal 'TIFF image data', get_image_type(tiff)
97
+
98
+ assert_equal pixels, load(png) .then {|o| o.bitmap.to_a}
99
+ assert_equal [10, 10], load(jpg) .then {|o| [o.width, o.height]}
100
+ assert_equal [10, 10], load(jpeg).then {|o| [o.width, o.height]}
101
+ assert_equal pixels, load(gif) .then {|o| o.bitmap.to_a}
102
+ assert_equal [10, 10], load(bmp) .then {|o| [o.width, o.height]}
103
+ assert_equal pixels, load(tif) .then {|o| o.bitmap.to_a}
104
+ assert_equal pixels, load(tiff).then {|o| o.bitmap.to_a}
105
+
106
+ paths.each {|path| File.delete path}
107
+
108
+ assert_raise(ArgumentError) {img.save 'testimage.unknown'}
109
+ end
110
+
76
111
  end# TestImage
data/test/test_painter.rb CHANGED
@@ -18,6 +18,28 @@ class TestPainter < Test::Unit::TestCase
18
18
  Rays::Color.new(*args)
19
19
  end
20
20
 
21
+ def image(w = 16, h = 16, bg: 0, &block)
22
+ Rays::Image.new(w, h)
23
+ .paint {background bg}
24
+ .tap {|img| img.paint(&block) if block}
25
+ end
26
+
27
+ def assert_gray(expected, actual)
28
+ assert_in_epsilon expected, actual, 0.02
29
+ end
30
+
31
+ def assert_rgb(expected, actual)
32
+ (0..2).each do |i|
33
+ assert_gray expected[i], actual[i]
34
+ end
35
+ end
36
+
37
+ def assert_rgba(expected, actual)
38
+ (0..3).each do |i|
39
+ assert_gray expected[i], actual[i]
40
+ end
41
+ end
42
+
21
43
  def setup()
22
44
  Rays::Color.set_palette_color :rgb001, color(0, 0, 1)
23
45
  end
@@ -124,6 +146,19 @@ class TestPainter < Test::Unit::TestCase
124
146
  assert_equal 4, pa.miter_limit
125
147
  end
126
148
 
149
+ def test_blend_mode_accessor()
150
+ pa = painter
151
+ assert_equal :normal, pa.blend_mode
152
+ pa.blend_mode = :add
153
+ assert_equal :add, pa.blend_mode
154
+ pa.blend_mode :subtract
155
+ assert_equal :subtract, pa.blend_mode
156
+ pa.push blend_mode: :multiply do |_|
157
+ assert_equal :multiply, pa.blend_mode
158
+ end
159
+ assert_equal :subtract, pa.blend_mode
160
+ end
161
+
127
162
  def test_clip_accessor()
128
163
  pa = painter
129
164
  pa.clip = [1, 2, 3, 4]
@@ -182,6 +217,122 @@ class TestPainter < Test::Unit::TestCase
182
217
  assert_equal color(0, 1, 0), pa.fill
183
218
  end
184
219
 
220
+ def test_blend_mode_normal()
221
+ i = image do
222
+ blend_mode :normal
223
+ fill 0.1, 0.2, 0.3
224
+ rect 0, 0, 2
225
+ fill 0.4, 0.5, 0.6
226
+ rect 1, 0, 2
227
+ end
228
+ assert_rgb [0.1, 0.2, 0.3], i[0, 0]
229
+ assert_rgb [0.4, 0.5, 0.6], i[1, 0]
230
+ assert_rgb [0.4, 0.5, 0.6], i[2, 0]
231
+ end
232
+
233
+ def test_blend_mode_add()
234
+ i = image do
235
+ fill 0.1, 0.2, 0.3
236
+ rect 0, 0, 2
237
+ blend_mode :add
238
+ fill 0.4, 0.5, 0.6
239
+ rect 1, 0, 2
240
+ end
241
+ assert_rgb [0.1, 0.2, 0.3], i[0, 0]
242
+ assert_rgb [0.5, 0.7, 0.9], i[1, 0]
243
+ assert_rgb [0.4, 0.5, 0.6], i[2, 0]
244
+ end
245
+
246
+ def test_blend_mode_subtract()
247
+ i = image bg: 1 do
248
+ fill 0.4, 0.5, 0.6
249
+ rect 0, 0, 2
250
+ blend_mode :subtract
251
+ fill 0.1, 0.2, 0.3
252
+ rect 1, 0, 2
253
+ end
254
+ assert_rgb [0.4, 0.5, 0.6], i[0, 0]
255
+ assert_rgb [0.3, 0.3, 0.3], i[1, 0]
256
+ assert_rgb [0.9, 0.8, 0.7], i[2, 0]
257
+ end
258
+
259
+ def test_blend_mode_lightest()
260
+ i = image do
261
+ fill 0.4, 0.5, 0.6
262
+ rect 0, 0, 2
263
+ blend_mode :lightest
264
+ fill 0.1, 0.2, 0.3
265
+ rect 1, 0, 2
266
+ end
267
+ assert_rgb [0.4, 0.5, 0.6], i[0, 0]
268
+ assert_rgb [0.4, 0.5, 0.6], i[1, 0]
269
+ assert_rgb [0.1, 0.2, 0.3], i[2, 0]
270
+ end
271
+
272
+ def test_blend_mode_darkest()
273
+ i = image bg: 1 do
274
+ fill 0.1, 0.2, 0.3
275
+ rect 0, 0, 2
276
+ blend_mode :darkest
277
+ fill 0.4, 0.5, 0.6
278
+ rect 1, 0, 2
279
+ end
280
+ assert_rgb [0.1, 0.2, 0.3], i[0, 0]
281
+ assert_rgb [0.1, 0.2, 0.3], i[1, 0]
282
+ assert_rgb [0.4, 0.5, 0.6], i[2, 0]
283
+ end
284
+
285
+ def test_blend_mode_exclusion()
286
+ # no tests
287
+ end
288
+
289
+ def test_blend_mode_multiply()
290
+ i = image bg: 1 do
291
+ fill 0.2, 0.4, 0.6
292
+ rect 0, 0, 2
293
+ blend_mode :multiply
294
+ fill 0.5
295
+ rect 1, 0, 2
296
+ end
297
+ assert_rgb [0.2, 0.4, 0.6], i[0, 0]
298
+ assert_rgb [0.1, 0.2, 0.3], i[1, 0]
299
+ assert_rgb [0.5, 0.5, 0.5], i[2, 0]
300
+ end
301
+
302
+ def test_blend_mode_screen()
303
+ i = image bg: 0.8 do
304
+ fill 0.2, 0.4, 0.6
305
+ rect 0, 0, 2
306
+ blend_mode :screen
307
+ fill 0.5
308
+ rect 1, 0, 2
309
+ end
310
+ assert_rgb [0.2, 0.4, 0.6], i[0, 0]
311
+ assert_rgb [0.6, 0.7, 0.8], i[1, 0]
312
+ assert_rgb [0.9, 0.9, 0.9], i[2, 0]
313
+ end
314
+
315
+ def test_blend_mode_replace()
316
+ i = image bg: 1 do
317
+ fill 0.1, 0.2, 0.3, 0.4
318
+ rect 0, 0, 2
319
+ blend_mode :replace
320
+ fill 0.5, 0.6, 0.7, 0.8
321
+ rect 1, 0, 2
322
+ end
323
+ assert_rgba [0.5, 0.6, 0.7, 0.8], i[1, 0]
324
+ assert_rgba [0.5, 0.6, 0.7, 0.8], i[2, 0]
325
+ end
326
+
327
+ def test_blend_mode_invalid()
328
+ assert_raise(ArgumentError) do
329
+ image {blend_mode :invalid}
330
+ end
331
+ assert_raise(ArgumentError) do
332
+ image {blend_mode nil}
333
+ end
334
+ end
335
+
185
336
  def test_push()
186
337
  pa = painter
187
338
  pa.fill = [1, 0, 0]
@@ -224,7 +375,23 @@ class TestPainter < Test::Unit::TestCase
224
375
  end
225
376
 
226
377
  def test_shader()
227
- img = Rays::Image.new(10, 10).paint {
378
+ image.paint do |pa|
379
+ assert_nil pa.shader
380
+
381
+ pa.shader = Rays::Shader.new "void main() {gl_FragColor = vec4(0.0);}"
382
+ assert_instance_of Rays::Shader, pa.shader
383
+
384
+ pa.shader = nil
385
+ assert_nil pa.shader
386
+
387
+ pa.shader = "void main() {gl_FragColor = vec4(0.0);}"
388
+ assert_instance_of Rays::Shader, pa.shader
389
+
390
+ pa.no_shader
391
+ assert_nil pa.shader
392
+ end
393
+
394
+ img = image.paint {
228
395
  shader "void main() {gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);}"
229
396
  fill 1, 0, 0
230
397
  rect bounds
@@ -99,4 +99,4 @@ class TestPainterShape < Test::Unit::TestCase
99
99
  assert_equal 0, img[99, 99].a
100
100
  end
101
101
 
102
- end# TestPainter
102
+ end# TestPainterShape
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rays
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.25
4
+ version: 0.1.28
5
5
  platform: ruby
6
6
  authors:
7
7
  - xordog
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-04 00:00:00.000000000 Z
11
+ date: 2022-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: xot
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.1.25
19
+ version: 0.1.28
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.1.25
26
+ version: 0.1.28
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rucy
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.1.25
33
+ version: 0.1.28
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.1.25
40
+ version: 0.1.28
41
41
  description: This library helps you to develop graphics application with OpenGL.
42
42
  email: xordog@gmail.com
43
43
  executables: []
@@ -252,7 +252,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
252
252
  - !ruby/object:Gem::Version
253
253
  version: '0'
254
254
  requirements: []
255
- rubygems_version: 3.2.32
255
+ rubygems_version: 3.2.33
256
256
  signing_key:
257
257
  specification_version: 4
258
258
  summary: A Drawing Engine using OpenGL.