rmagick 3.1.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rmagick might be problematic. Click here for more details.

Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.appveyor.yml +4 -4
  3. data/.circleci/config.yml +1 -1
  4. data/.gitignore +1 -0
  5. data/.rubocop_todo.yml +6 -0
  6. data/.travis.yml +26 -8
  7. data/CHANGELOG.md +104 -0
  8. data/before_install_linux.sh +19 -10
  9. data/benchmarks/memory/README.md +50 -0
  10. data/benchmarks/memory/image_new.rb +8 -0
  11. data/benchmarks/memory/rmagick.gnuplot +16 -0
  12. data/doc/ex/coalesce.rb +2 -2
  13. data/doc/ex/drawcomp.rb +3 -3
  14. data/doc/ex/get_pixels.rb +1 -1
  15. data/doc/ex/images/Coffee.png +0 -0
  16. data/doc/ex/images/No.png +0 -0
  17. data/doc/ex/images/Snake.png +0 -0
  18. data/doc/ex/implode.rb +2 -2
  19. data/doc/ex/mask.rb +1 -1
  20. data/doc/ex/matte_fill_to_border.rb +1 -1
  21. data/doc/ex/matte_floodfill.rb +1 -1
  22. data/doc/ex/matte_replace.rb +1 -1
  23. data/doc/ex/stegano.rb +1 -1
  24. data/examples/constitute.rb +1 -1
  25. data/examples/crop_with_gravity.rb +1 -1
  26. data/examples/demo.rb +4 -4
  27. data/examples/find_similar_region.rb +1 -1
  28. data/examples/histogram.rb +3 -3
  29. data/examples/identify.rb +46 -46
  30. data/examples/image_opacity.rb +2 -2
  31. data/examples/vignette.rb +3 -3
  32. data/ext/RMagick/extconf.rb +19 -15
  33. data/ext/RMagick/rmagick.c +1 -2
  34. data/ext/RMagick/rmagick.h +59 -30
  35. data/ext/RMagick/rmdraw.c +62 -274
  36. data/ext/RMagick/rmenum.c +121 -665
  37. data/ext/RMagick/rmfill.c +7 -7
  38. data/ext/RMagick/rmilist.c +91 -7
  39. data/ext/RMagick/rmimage.c +568 -379
  40. data/ext/RMagick/rminfo.c +152 -110
  41. data/ext/RMagick/rmkinfo.c +17 -1
  42. data/ext/RMagick/rmmain.c +75 -74
  43. data/ext/RMagick/rmmontage.c +33 -33
  44. data/ext/RMagick/rmpixel.c +75 -14
  45. data/ext/RMagick/rmstruct.c +5 -5
  46. data/ext/RMagick/rmutil.c +3 -13
  47. data/lib/obsolete.rb +66 -0
  48. data/lib/rmagick/version.rb +1 -1
  49. data/lib/rmagick_internal.rb +54 -41
  50. data/spec/rmagick/image/composite_spec.rb +5 -76
  51. data/spec/rmagick/image/properties_spec.rb +1 -1
  52. data/test/Draw.rb +52 -115
  53. data/test/Enum.rb +153 -1
  54. data/test/Fill.rb +1 -1
  55. data/test/Image1.rb +97 -43
  56. data/test/Image2.rb +140 -36
  57. data/test/Image3.rb +110 -120
  58. data/test/ImageList1.rb +46 -11
  59. data/test/ImageList2.rb +11 -21
  60. data/test/Image_attributes.rb +81 -127
  61. data/test/Import_Export.rb +2 -2
  62. data/test/Info.rb +5 -1
  63. data/test/KernelInfo.rb +67 -0
  64. data/test/Magick.rb +17 -35
  65. data/test/Pixel.rb +193 -24
  66. data/test/PolaroidOptions.rb +1 -1
  67. data/test/Preview.rb +3 -35
  68. data/test/Struct.rb +45 -0
  69. data/test/appearance/Montage.rb +26 -0
  70. data/test/appearance/appearance_assertion.rb +13 -0
  71. data/test/appearance/expected/montage_border_color.jpg +0 -0
  72. data/test/lib/Obsolete.rb +30 -0
  73. data/test/lib/internal/Draw.rb +823 -0
  74. data/test/lib/internal/Geometry.rb +98 -0
  75. data/test/lib/internal/Magick.rb +40 -0
  76. data/test/test_all_basic.rb +16 -17
  77. metadata +27 -5
  78. data/doc/ex/images/Coffee.wmf +0 -0
  79. data/doc/ex/images/No.wmf +0 -0
  80. data/doc/ex/images/Snake.wmf +0 -0
@@ -110,6 +110,24 @@ DEF_ATTR_READER(Pixel, green, int)
110
110
  */
111
111
  DEF_ATTR_READER(Pixel, blue, int)
112
112
 
113
+ /**
114
+ * Get Pixel alpha attribute.
115
+ *
116
+ * Ruby usage:
117
+ * - @verbatim Pixel#alpha @endverbatim
118
+ *
119
+ * @param self this object
120
+ * @return the alpha value
121
+ */
122
+ VALUE
123
+ Pixel_alpha(VALUE self)
124
+ {
125
+ Pixel *pixel;
126
+ Data_Get_Struct(self, Pixel, pixel);
127
+ return C_int_to_R_int(QuantumRange - pixel->opacity);
128
+ }
129
+
130
+
113
131
  /**
114
132
  * Get Pixel opacity attribute.
115
133
  *
@@ -118,8 +136,16 @@ DEF_ATTR_READER(Pixel, blue, int)
118
136
  *
119
137
  * @param self this object
120
138
  * @return the opacity value
139
+ * @deprecated This method has been deprecated. Please use Pixel_alpha.
121
140
  */
122
- DEF_ATTR_READER(Pixel, opacity, int)
141
+ VALUE
142
+ Pixel_opacity(VALUE self)
143
+ {
144
+ Pixel *pixel;
145
+ rb_warning("Pixel#opacity is deprecated; use Pixel#alpha.");
146
+ Data_Get_Struct(self, Pixel, pixel);
147
+ return C_int_to_R_int(pixel->opacity);
148
+ }
123
149
 
124
150
  /**
125
151
  * Set Pixel red attribute.
@@ -172,6 +198,35 @@ DEF_PIXEL_CHANNEL_WRITER(green)
172
198
  */
173
199
  DEF_PIXEL_CHANNEL_WRITER(blue)
174
200
 
201
+ /**
202
+ * Set Pixel alpha attribute.
203
+ *
204
+ * Ruby usage:
205
+ * - @verbatim Pixel#alpha= @endverbatim
206
+ *
207
+ * Notes:
208
+ * - Pixel is Observable. Setters call changed, notify_observers
209
+ * - Setters return their argument values for backward compatibility to when
210
+ * Pixel was a Struct class.
211
+ *
212
+ * @param self this object
213
+ * @param v the alpha value
214
+ * @return self
215
+ */
216
+ VALUE
217
+ Pixel_alpha_eq(VALUE self, VALUE v)
218
+ {
219
+ Pixel *pixel;
220
+
221
+ rb_check_frozen(self);
222
+ Data_Get_Struct(self, Pixel, pixel);
223
+ pixel->opacity = QuantumRange - APP2QUANTUM(v);
224
+ (void) rb_funcall(self, rm_ID_changed, 0);
225
+ (void) rb_funcall(self, rm_ID_notify_observers, 1, self);
226
+ return QUANTUM2NUM(QuantumRange - pixel->opacity);
227
+ }
228
+
229
+
175
230
  /**
176
231
  * Set Pixel opacity attribute.
177
232
  *
@@ -186,9 +241,21 @@ DEF_PIXEL_CHANNEL_WRITER(blue)
186
241
  * @param self this object
187
242
  * @param v the opacity value
188
243
  * @return self
244
+ * @deprecated This method has been deprecated. Please use Pixel_alpha_eq.
189
245
  */
190
- DEF_PIXEL_CHANNEL_WRITER(opacity)
246
+ VALUE
247
+ Pixel_opacity_eq(VALUE self, VALUE v)
248
+ {
249
+ Pixel *pixel;
191
250
 
251
+ rb_warning("Pixel#opacity= is deprecated; use Pixel#alpha=.");
252
+ rb_check_frozen(self);
253
+ Data_Get_Struct(self, Pixel, pixel);
254
+ pixel->opacity = APP2QUANTUM(v);
255
+ (void) rb_funcall(self, rm_ID_changed, 0);
256
+ (void) rb_funcall(self, rm_ID_notify_observers, 1, self);
257
+ return QUANTUM2NUM(pixel->opacity);
258
+ }
192
259
 
193
260
  /*
194
261
  * Get/set Pixel CMYK attributes.
@@ -421,13 +488,12 @@ Pixel_eql_q(VALUE self, VALUE other)
421
488
  VALUE
422
489
  Pixel_fcmp(int argc, VALUE *argv, VALUE self)
423
490
  {
491
+ double fuzz = 0.0;
492
+ unsigned int equal;
493
+ ColorspaceType colorspace = RGBColorspace;
424
494
  Image *image;
425
495
  Info *info;
426
-
427
496
  Pixel *this, *that;
428
- ColorspaceType colorspace = RGBColorspace;
429
- double fuzz = 0.0;
430
- unsigned int equal;
431
497
 
432
498
  switch (argc)
433
499
  {
@@ -493,14 +559,12 @@ Pixel_fcmp(int argc, VALUE *argv, VALUE self)
493
559
  * @see Pixel_to_color
494
560
  */
495
561
  VALUE
496
- Pixel_from_color(VALUE class, VALUE name)
562
+ Pixel_from_color(VALUE class ATTRIBUTE_UNUSED, VALUE name)
497
563
  {
498
564
  PixelColor pp;
499
565
  ExceptionInfo *exception;
500
566
  MagickBooleanType okay;
501
567
 
502
- class = class; // defeat "never referenced" message from icc
503
-
504
568
  exception = AcquireExceptionInfo();
505
569
  okay = QueryColorCompliance(StringValuePtr(name), AllCompliance, &pp, exception);
506
570
  CHECK_EXCEPTION()
@@ -536,7 +600,7 @@ Pixel_from_color(VALUE class, VALUE name)
536
600
  * @return a new Magick::Pixel object
537
601
  */
538
602
  VALUE
539
- Pixel_from_hsla(int argc, VALUE *argv, VALUE class)
603
+ Pixel_from_hsla(int argc, VALUE *argv, VALUE class ATTRIBUTE_UNUSED)
540
604
  {
541
605
  double h, s, l, a = 1.0;
542
606
  MagickPixel pp;
@@ -544,8 +608,6 @@ Pixel_from_hsla(int argc, VALUE *argv, VALUE class)
544
608
  char name[50];
545
609
  MagickBooleanType alpha = MagickFalse;
546
610
 
547
- class = class; // defeat "unused parameter" message.
548
-
549
611
  switch (argc)
550
612
  {
551
613
  case 4:
@@ -613,12 +675,11 @@ Pixel_from_hsla(int argc, VALUE *argv, VALUE class)
613
675
  * @deprecated This method has been deprecated. Please use Pixel_from_hsla.
614
676
  */
615
677
  VALUE
616
- Pixel_from_HSL(VALUE class, VALUE hsl)
678
+ Pixel_from_HSL(VALUE class ATTRIBUTE_UNUSED, VALUE hsl)
617
679
  {
618
680
  PixelColor rgb;
619
681
  double hue, saturation, luminosity;
620
682
 
621
- class = class; // defeat "never referenced" message from icc
622
683
  memset(&rgb, 0, sizeof(rgb));
623
684
 
624
685
  hsl = rb_Array(hsl); // Ensure array
@@ -233,7 +233,7 @@ Import_ColorInfo(const ColorInfo *ci)
233
233
  name = rb_str_new2(ci->name);
234
234
 
235
235
  compliance_type = ci->compliance;
236
- compliance = ComplianceType_new(compliance_type);
236
+ compliance = ComplianceType_find(compliance_type);
237
237
  color = Pixel_from_MagickPixel(&(ci->color));
238
238
 
239
239
  RB_GC_GUARD(name);
@@ -390,8 +390,8 @@ Import_TypeInfo(const TypeInfo *ti)
390
390
 
391
391
  name = rb_str_new2(ti->name);
392
392
  family = rb_str_new2(ti->family);
393
- style = StyleType_new(ti->style);
394
- stretch = StretchType_new(ti->stretch);
393
+ style = StyleType_find(ti->style);
394
+ stretch = StretchType_find(ti->stretch);
395
395
  weight = ULONG2NUM(ti->weight);
396
396
  description = ti->description ? rb_str_new2(ti->description) : Qnil;
397
397
  encoding = ti->encoding ? rb_str_new2(ti->encoding) : Qnil;
@@ -451,8 +451,8 @@ Export_TypeInfo(TypeInfo *ti, VALUE st)
451
451
  {
452
452
  (void) CloneString((char **)&(ti->family), StringValuePtr(m));
453
453
  }
454
- m = rb_ary_entry(members, 3); ti->style = m == Qnil ? 0 : FIX2INT(m);
455
- m = rb_ary_entry(members, 4); ti->stretch = m == Qnil ? 0 : FIX2INT(m);
454
+ m = rb_ary_entry(members, 3); ti->style = m == Qnil ? 0 : FIX2INT(Enum_to_i(m));
455
+ m = rb_ary_entry(members, 4); ti->stretch = m == Qnil ? 0 : FIX2INT(Enum_to_i(m));
456
456
  m = rb_ary_entry(members, 5); ti->weight = m == Qnil ? 0 : FIX2INT(m);
457
457
 
458
458
  m = rb_ary_entry(members, 6);
@@ -359,10 +359,7 @@ rm_str2cstr(VALUE str, long *len)
359
359
  static VALUE
360
360
  arg_is_number(VALUE arg)
361
361
  {
362
- double d;
363
- d = NUM2DBL(arg);
364
- d = d; // satisfy icc
365
- return arg;
362
+ return DBL2NUM(NUM2DBL(arg));
366
363
  }
367
364
 
368
365
 
@@ -472,9 +469,8 @@ check_num2dbl(VALUE obj)
472
469
  * @return 0
473
470
  */
474
471
  static VALUE
475
- rescue_not_dbl(VALUE ignored)
472
+ rescue_not_dbl(VALUE ignored ATTRIBUTE_UNUSED)
476
473
  {
477
- ignored = ignored; // defeat gcc message
478
474
  return INT2FIX(0);
479
475
  }
480
476
 
@@ -1490,7 +1486,7 @@ rm_clone_image(Image *image)
1490
1486
  */
1491
1487
  MagickBooleanType
1492
1488
  rm_progress_monitor(
1493
- const char *tag,
1489
+ const char *tag ATTRIBUTE_UNUSED,
1494
1490
  const MagickOffsetType of,
1495
1491
  const MagickSizeType sp,
1496
1492
  void *client_data)
@@ -1509,8 +1505,6 @@ rm_progress_monitor(
1509
1505
  return MagickTrue;
1510
1506
  }
1511
1507
 
1512
- tag = tag; // defeat gcc message
1513
-
1514
1508
  #if defined(HAVE_LONG_LONG) // defined in Ruby's defines.h
1515
1509
  offset = rb_ll2inum(of);
1516
1510
  span = rb_ull2inum(sp);
@@ -1625,11 +1619,7 @@ format_exception(const ExceptionType severity, const char *reason, const char *d
1625
1619
  int len;
1626
1620
  memset(msg, 0, sizeof(ERROR_MSG_SIZE));
1627
1621
 
1628
- #if defined(HAVE_SNPRINTF)
1629
1622
  len = snprintf(msg, ERROR_MSG_SIZE, "%s%s%s",
1630
- #else
1631
- len = sprintf(msg, "%.500s%s%.500s",
1632
- #endif
1633
1623
  GetLocaleExceptionMessage(severity, reason),
1634
1624
  description ? ": " : "",
1635
1625
  description ? GetLocaleExceptionMessage(severity, description) : "");
@@ -0,0 +1,66 @@
1
+ module Magick
2
+ AddCompositeOp = ModulusAddCompositeOp
3
+ deprecate_constant 'AddCompositeOp'
4
+
5
+ AlphaChannelType = AlphaChannelOption
6
+ deprecate_constant 'AlphaChannelType'
7
+
8
+ ColorSeparationMatteType = ColorSeparationAlphaType
9
+ deprecate_constant 'ColorSeparationMatteType'
10
+
11
+ CopyOpacityCompositeOp = CopyAlphaCompositeOp
12
+ deprecate_constant 'CopyOpacityCompositeOp'
13
+
14
+ DistortImageMethod = DistortMethod
15
+ deprecate_constant 'DistortImageMethod'
16
+
17
+ DivideCompositeOp = DivideDstCompositeOp
18
+ deprecate_constant 'DivideDstCompositeOp'
19
+
20
+ FilterTypes = FilterType
21
+ deprecate_constant 'FilterTypes'
22
+
23
+ GrayscaleMatteType = GrayscaleAlphaType
24
+ deprecate_constant 'GrayscaleMatteType'
25
+
26
+ ImageLayerMethod = LayerMethod
27
+ deprecate_constant 'ImageLayerMethod'
28
+
29
+ InterpolatePixelMethod = PixelInterpolateMethod
30
+ deprecate_constant 'InterpolatePixelMethod'
31
+
32
+ MeanErrorPerPixelMetric = MeanErrorPerPixelErrorMetric
33
+ deprecate_constant 'MeanErrorPerPixelMetric'
34
+
35
+ MinusCompositeOp = MinusDstCompositeOp
36
+ deprecate_constant 'MinusCompositeOp'
37
+
38
+ PaletteBilevelMatteType = PaletteBilevelAlphaType
39
+ deprecate_constant 'PaletteBilevelMatteType'
40
+
41
+ PaletteMatteType = PaletteAlphaType
42
+ deprecate_constant 'PaletteMatteType'
43
+
44
+ PeakSignalToNoiseRatioMetric = PeakSignalToNoiseRatioErrorMetric
45
+ deprecate_constant 'PeakSignalToNoiseRatioMetric'
46
+
47
+ SubtractCompositeOp = ModulusSubtractCompositeOp
48
+ deprecate_constant 'SubtractCompositeOp'
49
+
50
+ TrueColorMatteType = TrueColorAlphaType
51
+ deprecate_constant 'TrueColorMatteType'
52
+
53
+ UndefinedMetric = UndefinedErrorMetric
54
+ deprecate_constant 'UndefinedMetric'
55
+
56
+ deprecate_constant 'ConstantVirtualPixelMethod'
57
+ deprecate_constant 'FlattenAlphaChannel'
58
+ deprecate_constant 'IntegerPixel'
59
+ deprecate_constant 'MatteChannel'
60
+ deprecate_constant 'OpaqueOpacity'
61
+ deprecate_constant 'Rec601LumaColorspace'
62
+ deprecate_constant 'Rec709LumaColorspace'
63
+ deprecate_constant 'ResetAlphaChannel'
64
+ deprecate_constant 'StaticGravity'
65
+ deprecate_constant 'TransparentOpacity'
66
+ end
@@ -1,5 +1,5 @@
1
1
  module Magick
2
- VERSION = '3.1.0'
2
+ VERSION = '3.2.0'
3
3
  MIN_RUBY_VERSION = '2.3.0'
4
4
  MIN_IM_VERSION = '6.7.7'
5
5
  end
@@ -20,6 +20,7 @@ end
20
20
 
21
21
  require 'English'
22
22
  require 'RMagick2.so'
23
+ require 'obsolete.rb'
23
24
 
24
25
  module Magick
25
26
  @formats = nil
@@ -220,6 +221,13 @@ module Magick
220
221
  end
221
222
  end
222
223
 
224
+ def check_opacity(opacity)
225
+ return if opacity.is_a?(String) && opacity['%']
226
+
227
+ value = Float(opacity)
228
+ Kernel.raise ArgumentError, 'opacity must be >= 0 and <= 1.0' if value < 0 || value > 1.0
229
+ end
230
+
223
231
  public
224
232
 
225
233
  # Apply coordinate transformations to support scaling (s), rotation (r),
@@ -228,6 +236,13 @@ module Magick
228
236
  primitive 'affine ' + format('%g,%g,%g,%g,%g,%g', sx, rx, ry, sy, tx, ty)
229
237
  end
230
238
 
239
+ # Set alpha (make transparent) in image according to the specified
240
+ # colorization rule
241
+ def alpha(x, y, method)
242
+ Kernel.raise ArgumentError, 'Unknown paint method' unless PAINT_METHOD_NAMES.key?(method.to_i)
243
+ primitive 'matte ' + format('%g,%g, %s', x, y, PAINT_METHOD_NAMES[method.to_i])
244
+ end
245
+
231
246
  # Draw an arc.
232
247
  def arc(start_x, start_y, end_x, end_y, start_degrees, end_degrees)
233
248
  primitive 'arc ' + format('%g,%g %g,%g %g,%g',
@@ -241,7 +256,7 @@ module Magick
241
256
  elsif points.length.odd?
242
257
  Kernel.raise ArgumentError, 'odd number of arguments specified'
243
258
  end
244
- primitive 'bezier ' + points.join(',')
259
+ primitive 'bezier ' + points.map! { |x| format('%g', x) }.join(',')
245
260
  end
246
261
 
247
262
  # Draw a circle
@@ -270,7 +285,7 @@ module Magick
270
285
  # point, replace, floodfill, filltoborder,reset
271
286
  def color(x, y, method)
272
287
  Kernel.raise ArgumentError, "Unknown PaintMethod: #{method}" unless PAINT_METHOD_NAMES.key?(method.to_i)
273
- primitive "color #{x},#{y},#{PAINT_METHOD_NAMES[method.to_i]}"
288
+ primitive 'color ' + format('%g,%g,%s', x, y, PAINT_METHOD_NAMES[method.to_i])
274
289
  end
275
290
 
276
291
  # Specify EITHER the text decoration (none, underline, overline,
@@ -290,7 +305,7 @@ module Magick
290
305
  # (pop) graphic-context".
291
306
  def define_clip_path(name)
292
307
  push('defs')
293
- push('clip-path', name)
308
+ push("clip-path \"#{name}\"")
294
309
  push('graphic-context')
295
310
  yield
296
311
  ensure
@@ -320,6 +335,7 @@ module Magick
320
335
 
321
336
  # Specify fill opacity (use "xx%" to indicate percentage)
322
337
  def fill_opacity(opacity)
338
+ check_opacity(opacity)
323
339
  primitive "fill-opacity #{opacity}"
324
340
  end
325
341
 
@@ -350,10 +366,10 @@ module Magick
350
366
  # The font weight argument can be either a font weight
351
367
  # constant or [100,200,...,900]
352
368
  def font_weight(weight)
353
- if FONT_WEIGHT_NAMES.key?(weight.to_i)
369
+ if weight.is_a?(WeightType)
354
370
  primitive "font-weight #{FONT_WEIGHT_NAMES[weight.to_i]}"
355
371
  else
356
- primitive "font-weight #{weight}"
372
+ primitive "font-weight #{Integer(weight)}"
357
373
  end
358
374
  end
359
375
 
@@ -364,6 +380,12 @@ module Magick
364
380
  primitive "gravity #{GRAVITY_NAMES[grav.to_i]}"
365
381
  end
366
382
 
383
+ def image(composite, x, y, width, height, image_file_path)
384
+ Kernel.raise ArgumentError, 'Unknown composite' unless composite.is_a?(CompositeOperator)
385
+ composite_name = composite.to_s.sub!('CompositeOp', '')
386
+ primitive 'image ' + format('%s %g,%g %g,%g %s', composite_name, x, y, width, height, enquote(image_file_path))
387
+ end
388
+
367
389
  # IM 6.5.5-8 and later
368
390
  def interline_spacing(space)
369
391
  begin
@@ -408,16 +430,15 @@ module Magick
408
430
  # Set matte (make transparent) in image according to the specified
409
431
  # colorization rule
410
432
  def matte(x, y, method)
433
+ Kernel.warn 'Draw#matte is deprecated. Use Draw#alpha instead.'
411
434
  Kernel.raise ArgumentError, 'Unknown paint method' unless PAINT_METHOD_NAMES.key?(method.to_i)
412
- primitive "matte #{x},#{y} #{PAINT_METHOD_NAMES[method.to_i]}"
435
+ primitive 'matte ' + format('%g,%g, %s', x, y, PAINT_METHOD_NAMES[method.to_i])
413
436
  end
414
437
 
415
438
  # Specify drawing fill and stroke opacities. If the value is a string
416
439
  # ending with a %, the number will be multiplied by 0.01.
417
440
  def opacity(opacity)
418
- if opacity.is_a?(Numeric)
419
- Kernel.raise ArgumentError, 'opacity must be >= 0 and <= 1.0' if opacity < 0 || opacity > 1.0
420
- end
441
+ check_opacity(opacity)
421
442
  primitive "opacity #{opacity}"
422
443
  end
423
444
 
@@ -433,7 +454,7 @@ module Magick
433
454
  # as the argument to the 'fill' or 'stroke' methods
434
455
  def pattern(name, x, y, width, height)
435
456
  push('defs')
436
- push("pattern #{name} #{x} #{y} #{width} #{height}")
457
+ push("pattern #{name} " + format('%g %g %g %g', x, y, width, height))
437
458
  push('graphic-context')
438
459
  yield
439
460
  ensure
@@ -444,13 +465,13 @@ module Magick
444
465
 
445
466
  # Set point to fill color.
446
467
  def point(x, y)
447
- primitive "point #{x},#{y}"
468
+ primitive 'point ' + format('%g,%g', x, y)
448
469
  end
449
470
 
450
471
  # Specify the font size in points. Yes, the primitive is "font-size" but
451
472
  # in other places this value is called the "pointsize". Give it both names.
452
473
  def pointsize(points)
453
- primitive "font-size #{points}"
474
+ primitive 'font-size ' + format('%g', points)
454
475
  end
455
476
  alias font_size pointsize
456
477
 
@@ -461,7 +482,7 @@ module Magick
461
482
  elsif points.length.odd?
462
483
  Kernel.raise ArgumentError, 'odd number of points specified'
463
484
  end
464
- primitive 'polygon ' + points.join(',')
485
+ primitive 'polygon ' + points.map! { |x| format('%g', x) }.join(',')
465
486
  end
466
487
 
467
488
  # Draw a polyline
@@ -471,7 +492,7 @@ module Magick
471
492
  elsif points.length.odd?
472
493
  Kernel.raise ArgumentError, 'odd number of points specified'
473
494
  end
474
- primitive 'polyline ' + points.join(',')
495
+ primitive 'polyline ' + points.map! { |x| format('%g', x) }.join(',')
475
496
  end
476
497
 
477
498
  # Return to the previously-saved set of whatever
@@ -511,7 +532,7 @@ module Magick
511
532
 
512
533
  # Specify coordinate space rotation. "angle" is measured in degrees
513
534
  def rotate(angle)
514
- primitive "rotate #{angle}"
535
+ primitive 'rotate ' + format('%g', angle)
515
536
  end
516
537
 
517
538
  # Draw a rectangle with rounded corners
@@ -522,15 +543,15 @@ module Magick
522
543
 
523
544
  # Specify scaling to be applied to coordinate space on subsequent drawing commands.
524
545
  def scale(x, y)
525
- primitive "scale #{x},#{y}"
546
+ primitive 'scale ' + format('%g,%g', x, y)
526
547
  end
527
548
 
528
549
  def skewx(angle)
529
- primitive "skewX #{angle}"
550
+ primitive 'skewX ' + format('%g', angle)
530
551
  end
531
552
 
532
553
  def skewy(angle)
533
- primitive "skewY #{angle}"
554
+ primitive 'skewY ' + format('%g', angle)
534
555
  end
535
556
 
536
557
  # Specify the object stroke, a color name or pattern name.
@@ -560,7 +581,7 @@ module Magick
560
581
 
561
582
  # Specify the initial offset in the dash pattern
562
583
  def stroke_dashoffset(value = 0)
563
- primitive "stroke-dashoffset #{value}"
584
+ primitive 'stroke-dashoffset ' + format('%g', value)
564
585
  end
565
586
 
566
587
  def stroke_linecap(value)
@@ -580,13 +601,14 @@ module Magick
580
601
 
581
602
  # Specify opacity of stroke drawing color
582
603
  # (use "xx%" to indicate percentage)
583
- def stroke_opacity(value)
584
- primitive "stroke-opacity #{value}"
604
+ def stroke_opacity(opacity)
605
+ check_opacity(opacity)
606
+ primitive "stroke-opacity #{opacity}"
585
607
  end
586
608
 
587
609
  # Specify stroke (outline) width in pixels.
588
610
  def stroke_width(pixels)
589
- primitive "stroke-width #{pixels}"
611
+ primitive 'stroke-width ' + format('%g', pixels)
590
612
  end
591
613
 
592
614
  # Draw text at position x,y. Add quotes to text that is not already quoted.
@@ -604,7 +626,7 @@ module Magick
604
626
  # escape existing braces, surround with braces
605
627
  text = '{' + text.gsub(/[}]/) { |b| '\\' + b } + '}'
606
628
  end
607
- primitive "text #{x},#{y} #{text}"
629
+ primitive 'text ' + format('%g,%g %s', x, y, text)
608
630
  end
609
631
 
610
632
  # Specify text alignment relative to a given point
@@ -633,7 +655,7 @@ module Magick
633
655
  # Specify center of coordinate space to use for subsequent drawing
634
656
  # commands.
635
657
  def translate(x, y)
636
- primitive "translate #{x},#{y}"
658
+ primitive 'translate ' + format('%g,%g', x, y)
637
659
  end
638
660
  end # class Magick::Draw
639
661
 
@@ -904,9 +926,9 @@ module Magick
904
926
  # Make the pixel at (x,y) transparent.
905
927
  def matte_point(x, y)
906
928
  f = copy
907
- f.opacity = OpaqueOpacity unless f.matte
929
+ f.alpha(OpaqueAlphaChannel) unless f.alpha?
908
930
  pixel = f.pixel_color(x, y)
909
- pixel.opacity = TransparentOpacity
931
+ pixel.alpha = TransparentAlpha
910
932
  f.pixel_color(x, y, pixel)
911
933
  f
912
934
  end
@@ -915,7 +937,7 @@ module Magick
915
937
  # pixel at (x, y).
916
938
  def matte_replace(x, y)
917
939
  f = copy
918
- f.opacity = OpaqueOpacity unless f.matte
940
+ f.alpha(OpaqueAlphaChannel) unless f.alpha?
919
941
  target = f.pixel_color(x, y)
920
942
  f.transparent(target)
921
943
  end
@@ -924,23 +946,21 @@ module Magick
924
946
  # at (x,y) and is a neighbor.
925
947
  def matte_floodfill(x, y)
926
948
  f = copy
927
- f.opacity = OpaqueOpacity unless f.matte
949
+ f.alpha(OpaqueAlphaChannel) unless f.alpha?
928
950
  target = f.pixel_color(x, y)
929
- f.matte_flood_fill(target, TransparentOpacity,
930
- x, y, FloodfillMethod)
951
+ f.matte_flood_fill(target, x, y, FloodfillMethod, alpha: TransparentAlpha)
931
952
  end
932
953
 
933
954
  # Make transparent any neighbor pixel that is not the border color.
934
955
  def matte_fill_to_border(x, y)
935
956
  f = copy
936
- f.opacity = Magick::OpaqueOpacity unless f.matte
937
- f.matte_flood_fill(border_color, TransparentOpacity,
938
- x, y, FillToBorderMethod)
957
+ f.alpha(OpaqueAlphaChannel) unless f.alpha?
958
+ f.matte_flood_fill(border_color, x, y, FillToBorderMethod, alpha: TransparentAlpha)
939
959
  end
940
960
 
941
961
  # Make all pixels transparent.
942
962
  def matte_reset!
943
- self.opacity = Magick::TransparentOpacity
963
+ alpha(TransparentAlphaChannel)
944
964
  self
945
965
  end
946
966
 
@@ -1376,13 +1396,6 @@ module Magick
1376
1396
  end
1377
1397
  alias size length
1378
1398
 
1379
- # Array#nitems is not available in 1.9
1380
- if Array.instance_methods.include?('nitems')
1381
- def nitems
1382
- @images.nitems
1383
- end
1384
- end
1385
-
1386
1399
  def clear
1387
1400
  @scene = nil
1388
1401
  @images.clear