rmagick 4.2.5 → 5.5.0

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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/Dockerfile +14 -0
  3. data/.devcontainer/ImageMagick6/devcontainer.json +11 -0
  4. data/.devcontainer/devcontainer.json +11 -0
  5. data/.devcontainer/setup-repo.sh +10 -0
  6. data/.devcontainer/setup-user.sh +45 -0
  7. data/.editorconfig +1 -1
  8. data/.github/workflows/ci.yml +90 -9
  9. data/.gitignore +4 -0
  10. data/.rubocop_todo.yml +16 -9
  11. data/.yardopts +1 -1
  12. data/CHANGELOG.md +141 -0
  13. data/Gemfile +20 -0
  14. data/README.md +12 -17
  15. data/Rakefile +63 -80
  16. data/before_install_linux.sh +4 -4
  17. data/before_install_osx.sh +7 -6
  18. data/ext/RMagick/extconf.rb +113 -52
  19. data/ext/RMagick/{rmagick.c → rmagick.cpp} +19 -22
  20. data/ext/RMagick/rmagick.h +88 -59
  21. data/ext/RMagick/rmagick_gvl.h +224 -0
  22. data/ext/RMagick/{rmdraw.c → rmdraw.cpp} +170 -159
  23. data/ext/RMagick/{rmenum.c → rmenum.cpp} +69 -50
  24. data/ext/RMagick/{rmfill.c → rmfill.cpp} +85 -24
  25. data/ext/RMagick/{rmilist.c → rmilist.cpp} +191 -93
  26. data/ext/RMagick/{rmimage.c → rmimage.cpp} +1544 -989
  27. data/ext/RMagick/{rminfo.c → rminfo.cpp} +140 -152
  28. data/ext/RMagick/{rmkinfo.c → rmkinfo.cpp} +46 -34
  29. data/ext/RMagick/rmmain.cpp +1923 -0
  30. data/ext/RMagick/{rmmontage.c → rmmontage.cpp} +50 -29
  31. data/ext/RMagick/{rmpixel.c → rmpixel.cpp} +108 -83
  32. data/ext/RMagick/{rmstruct.c → rmstruct.cpp} +6 -6
  33. data/ext/RMagick/{rmutil.c → rmutil.cpp} +62 -161
  34. data/lib/rmagick/version.rb +3 -1
  35. data/lib/rmagick.rb +2 -0
  36. data/lib/rmagick_internal.rb +76 -110
  37. data/lib/rvg/embellishable.rb +6 -2
  38. data/lib/rvg/misc.rb +7 -7
  39. data/lib/rvg/rvg.rb +2 -0
  40. data/lib/rvg/stretchable.rb +2 -2
  41. data/lib/rvg/transformable.rb +1 -1
  42. data/rmagick.gemspec +6 -17
  43. data/sig/rmagick/_draw_common_methods.rbs +64 -0
  44. data/sig/rmagick/_image_common_methods.rbs +389 -0
  45. data/sig/rmagick/draw.rbs +38 -0
  46. data/sig/rmagick/draw_attribute.rbs +28 -0
  47. data/sig/rmagick/enum.rbs +814 -0
  48. data/sig/rmagick/error.rbs +11 -0
  49. data/sig/rmagick/fill.rbs +21 -0
  50. data/sig/rmagick/geometry.rbs +14 -0
  51. data/sig/rmagick/image.rbs +194 -0
  52. data/sig/rmagick/image_list.rbs +181 -0
  53. data/sig/rmagick/iptc.rbs +101 -0
  54. data/sig/rmagick/kernel_info.rbs +12 -0
  55. data/sig/rmagick/optional_method_arguments.rbs +10 -0
  56. data/sig/rmagick/pixel.rbs +46 -0
  57. data/sig/rmagick/struct.rbs +90 -0
  58. data/sig/rmagick.rbs +43 -0
  59. data/sig/rvg/clippath.rbs +34 -0
  60. data/sig/rvg/container.rbs +78 -0
  61. data/sig/rvg/deep_equal.rbs +48 -0
  62. data/sig/rvg/describable.rbs +30 -0
  63. data/sig/rvg/embellishable.rbs +226 -0
  64. data/sig/rvg/misc.rbs +145 -0
  65. data/sig/rvg/paint.rbs +55 -0
  66. data/sig/rvg/pathdata.rbs +77 -0
  67. data/sig/rvg/rvg.rbs +125 -0
  68. data/sig/rvg/stretchable.rbs +56 -0
  69. data/sig/rvg/stylable.rbs +66 -0
  70. data/sig/rvg/text.rbs +118 -0
  71. data/sig/rvg/transformable.rbs +59 -0
  72. data/sig/rvg/units.rbs +33 -0
  73. metadata +63 -128
  74. data/.codeclimate.yml +0 -63
  75. data/deprecated/RMagick.rb +0 -6
  76. data/ext/RMagick/rmmain.c +0 -1951
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # $Id: RMagick.rb,v 1.84 2009/09/15 22:08:41 rmagick Exp $
2
4
  #==============================================================================
3
5
  # Copyright (C) 2009 by Timothy P. Hunter
@@ -12,7 +14,7 @@ if RUBY_PLATFORM =~ /mingw/i
12
14
  begin
13
15
  require 'ruby_installer'
14
16
  ENV['PATH'].split(File::PATH_SEPARATOR).grep(/ImageMagick/i).each do |path|
15
- RubyInstaller::Runtime.add_dll_directory(path)
17
+ RubyInstaller::Runtime.add_dll_directory(path) if File.exist?(File.join(path, 'CORE_RL_magick_.dll')) || File.exist?(File.join(path, 'CORE_RL_MagickCore_.dll'))
16
18
  end
17
19
  rescue LoadError
18
20
  end
@@ -23,9 +25,6 @@ require 'observer'
23
25
  require 'RMagick2.so'
24
26
 
25
27
  module Magick
26
- @formats = nil
27
- @trace_proc = nil
28
- @exit_block_set_up = nil
29
28
  IMAGEMAGICK_VERSION = Magick::Magick_version.split[1].split('-').first
30
29
 
31
30
  class << self
@@ -53,43 +52,14 @@ module Magick
53
52
  # => {"3FR"=>" r-+", "3G2"=>" r-+", "3GP"=>" r-+", "A"=>"*rw+",
54
53
  # ...
55
54
  def formats
56
- @formats ||= init_formats
55
+ formats = init_formats
57
56
 
58
57
  if block_given?
59
- @formats.each { |k, v| yield k, v }
58
+ formats.each { |k, v| yield k, v }
60
59
  self
61
60
  else
62
- @formats
63
- end
64
- end
65
-
66
- # If the Magick module attribute +trace_proc+ is set to a Proc object,
67
- # RMagick calls the proc whenever an image is created or destroyed.
68
- #
69
- # You can use this proc to keep track of which images your program has created
70
- # and which have been destroyed.
71
- #
72
- # @param p [Proc] The proc object.
73
- # The following value will be passed into the proc object.
74
- # - +which+ - A symbol that indicates which operation the proc is being called for.
75
- # If the proc is called for an image creation, the value is +:c+.
76
- # If called for an image destruction, the value is +:d+.
77
- # - +description+ - A string describing the image. This is the same string that
78
- # would be returned by calling the image's inspect method.
79
- # - +id+ - A unique identifier for the image. This identifier is not the same as the object's +object_id+.
80
- # - +method+ - The name of the method responsible for creating or destroying the image.
81
- #
82
- # @example
83
- # Magick.trace_proc = proc do |which, description, id, method|
84
- # ...
85
- # end
86
- def trace_proc=(p)
87
- if @trace_proc.nil? && !p.nil? && !@exit_block_set_up
88
- at_exit { @trace_proc = nil }
89
- @exit_block_set_up = true
61
+ formats
90
62
  end
91
-
92
- @trace_proc = p
93
63
  end
94
64
  end
95
65
 
@@ -106,7 +76,7 @@ module Magick
106
76
  MinimumGeometry = GeometryValue.new(:MinimumGeometry, 6).freeze
107
77
 
108
78
  class Geometry
109
- FLAGS = ['', '%', '!', '<', '>', '@', '^']
79
+ FLAGS = ['', '%', '!', '<', '>', '@', '^'].freeze
110
80
  RFLAGS = {
111
81
  '%' => PercentGeometry,
112
82
  '!' => AspectGeometry,
@@ -114,7 +84,7 @@ module Magick
114
84
  '>' => GreaterGeometry,
115
85
  '@' => AreaGeometry,
116
86
  '^' => MinimumGeometry
117
- }
87
+ }.freeze
118
88
 
119
89
  attr_accessor :width, :height, :x, :y, :flag
120
90
 
@@ -170,7 +140,7 @@ module Magick
170
140
 
171
141
  # Convert object to a geometry string
172
142
  def to_s
173
- str = ''
143
+ str = String.new
174
144
  if @width > 0
175
145
  fmt = @width.truncate == @width ? '%d' : '%.2f'
176
146
  str << sprintf(fmt, @width)
@@ -256,6 +226,7 @@ module Magick
256
226
  private
257
227
 
258
228
  def enquote(str)
229
+ str = to_string(str)
259
230
  if str.length > 2 && /\A(?:\"[^\"]+\"|\'[^\']+\'|\{[^\}]+\})\z/.match(str)
260
231
  str
261
232
  else
@@ -263,11 +234,21 @@ module Magick
263
234
  end
264
235
  end
265
236
 
266
- def check_opacity(opacity)
267
- return if opacity.is_a?(String) && opacity['%']
237
+ def to_opacity(opacity)
238
+ return opacity if opacity.is_a?(String) && opacity.end_with?('%')
268
239
 
269
240
  value = Float(opacity)
270
241
  Kernel.raise ArgumentError, 'opacity must be >= 0 and <= 1.0' if value < 0 || value > 1.0
242
+
243
+ value
244
+ end
245
+
246
+ def to_string(obj)
247
+ return obj if obj.is_a?(String)
248
+ return obj.to_s if obj.is_a?(Symbol)
249
+ return obj.to_str if obj.respond_to?(:to_str)
250
+
251
+ Kernel.raise TypeError, "no implicit conversion of #{obj.class} into String"
271
252
  end
272
253
 
273
254
  public
@@ -311,17 +292,19 @@ module Magick
311
292
 
312
293
  # Invoke a clip-path defined by def_clip_path.
313
294
  def clip_path(name)
314
- primitive "clip-path #{name}"
295
+ primitive "clip-path #{to_string(name)}"
315
296
  end
316
297
 
317
298
  # Define the clipping rule.
318
299
  def clip_rule(rule)
300
+ rule = to_string(rule)
319
301
  Kernel.raise ArgumentError, "Unknown clipping rule #{rule}" unless %w[evenodd nonzero].include?(rule.downcase)
320
302
  primitive "clip-rule #{rule}"
321
303
  end
322
304
 
323
305
  # Define the clip units
324
306
  def clip_units(unit)
307
+ unit = to_string(unit)
325
308
  Kernel.raise ArgumentError, "Unknown clip unit #{unit}" unless %w[userspace userspaceonuse objectboundingbox].include?(unit.downcase)
326
309
  primitive "clip-units #{unit}"
327
310
  end
@@ -350,7 +333,7 @@ module Magick
350
333
  # (pop) graphic-context".
351
334
  def define_clip_path(name)
352
335
  push('defs')
353
- push("clip-path \"#{name}\"")
336
+ push("clip-path #{enquote(name)}")
354
337
  push('graphic-context')
355
338
  yield
356
339
  ensure
@@ -370,7 +353,7 @@ module Magick
370
353
  # Let anything through, but the only defined argument
371
354
  # is "UTF-8". All others are apparently ignored.
372
355
  def encoding(encoding)
373
- primitive "encoding #{encoding}"
356
+ primitive "encoding #{to_string(encoding)}"
374
357
  end
375
358
 
376
359
  # Specify object fill, a color name or pattern name
@@ -382,22 +365,23 @@ module Magick
382
365
 
383
366
  # Specify fill opacity (use "xx%" to indicate percentage)
384
367
  def fill_opacity(opacity)
385
- check_opacity(opacity)
368
+ opacity = to_opacity(opacity)
386
369
  primitive "fill-opacity #{opacity}"
387
370
  end
388
371
 
389
372
  def fill_rule(rule)
373
+ rule = to_string(rule)
390
374
  Kernel.raise ArgumentError, "Unknown fill rule #{rule}" unless %w[evenodd nonzero].include?(rule.downcase)
391
375
  primitive "fill-rule #{rule}"
392
376
  end
393
377
 
394
378
  # Specify text drawing font
395
379
  def font(name)
396
- primitive "font \'#{name}\'"
380
+ primitive "font #{enquote(name)}"
397
381
  end
398
382
 
399
383
  def font_family(name)
400
- primitive "font-family \'#{name}\'"
384
+ primitive "font-family #{enquote(name)}"
401
385
  end
402
386
 
403
387
  def font_stretch(stretch)
@@ -435,38 +419,17 @@ module Magick
435
419
 
436
420
  # IM 6.5.5-8 and later
437
421
  def interline_spacing(space)
438
- begin
439
- Float(space)
440
- rescue ArgumentError
441
- Kernel.raise ArgumentError, 'invalid value for interline_spacing'
442
- rescue TypeError
443
- Kernel.raise TypeError, "can't convert #{space.class} into Float"
444
- end
445
- primitive "interline-spacing #{space}"
422
+ primitive "interline-spacing #{Float(space)}"
446
423
  end
447
424
 
448
425
  # IM 6.4.8-3 and later
449
426
  def interword_spacing(space)
450
- begin
451
- Float(space)
452
- rescue ArgumentError
453
- Kernel.raise ArgumentError, 'invalid value for interword_spacing'
454
- rescue TypeError
455
- Kernel.raise TypeError, "can't convert #{space.class} into Float"
456
- end
457
- primitive "interword-spacing #{space}"
427
+ primitive "interword-spacing #{Float(space)}"
458
428
  end
459
429
 
460
430
  # IM 6.4.8-3 and later
461
431
  def kerning(space)
462
- begin
463
- Float(space)
464
- rescue ArgumentError
465
- Kernel.raise ArgumentError, 'invalid value for kerning'
466
- rescue TypeError
467
- Kernel.raise TypeError, "can't convert #{space.class} into Float"
468
- end
469
- primitive "kerning #{space}"
432
+ primitive "kerning #{Float(space)}"
470
433
  end
471
434
 
472
435
  # Draw a line
@@ -477,7 +440,7 @@ module Magick
477
440
  # Specify drawing fill and stroke opacities. If the value is a string
478
441
  # ending with a %, the number will be multiplied by 0.01.
479
442
  def opacity(opacity)
480
- check_opacity(opacity)
443
+ opacity = to_opacity(opacity)
481
444
  primitive "opacity #{opacity}"
482
445
  end
483
446
 
@@ -485,7 +448,7 @@ module Magick
485
448
  # primitive requires that the commands be surrounded by quotes or
486
449
  # apostrophes. Here we simply use apostrophes.
487
450
  def path(cmds)
488
- primitive "path '" + cmds + "'"
451
+ primitive "path #{enquote(cmds)}"
489
452
  end
490
453
 
491
454
  # Define a pattern. In the block, call primitive methods to
@@ -493,7 +456,7 @@ module Magick
493
456
  # as the argument to the 'fill' or 'stroke' methods
494
457
  def pattern(name, x, y, width, height)
495
458
  push('defs')
496
- push("pattern #{name} " + sprintf('%g %g %g %g', x, y, width, height))
459
+ push("pattern #{to_string(name)} " + sprintf('%g %g %g %g', x, y, width, height))
497
460
  push('graphic-context')
498
461
  yield
499
462
  ensure
@@ -544,8 +507,7 @@ module Magick
544
507
  if what.length.zero?
545
508
  primitive 'pop graphic-context'
546
509
  else
547
- # to_s allows a Symbol to be used instead of a String
548
- primitive 'pop ' + what.map(&:to_s).join(' ')
510
+ primitive 'pop ' + what.map { |x| to_string(x) }.join(' ')
549
511
  end
550
512
  end
551
513
 
@@ -558,8 +520,7 @@ module Magick
558
520
  if what.length.zero?
559
521
  primitive 'push graphic-context'
560
522
  else
561
- # to_s allows a Symbol to be used instead of a String
562
- primitive 'push ' + what.map(&:to_s).join(' ')
523
+ primitive 'push ' + what.map { |x| to_string(x) }.join(' ')
563
524
  end
564
525
  end
565
526
 
@@ -615,7 +576,7 @@ module Magick
615
576
  if list.length.zero?
616
577
  primitive 'stroke-dasharray none'
617
578
  else
618
- list.each do |x|
579
+ list.map! { |x| Float(x) }.each do |x|
619
580
  Kernel.raise ArgumentError, "dash array elements must be > 0 (#{x} given)" if x <= 0
620
581
  end
621
582
  primitive "stroke-dasharray #{list.join(',')}"
@@ -628,16 +589,19 @@ module Magick
628
589
  end
629
590
 
630
591
  def stroke_linecap(value)
592
+ value = to_string(value)
631
593
  Kernel.raise ArgumentError, "Unknown linecap type: #{value}" unless %w[butt round square].include?(value.downcase)
632
594
  primitive "stroke-linecap #{value}"
633
595
  end
634
596
 
635
597
  def stroke_linejoin(value)
598
+ value = to_string(value)
636
599
  Kernel.raise ArgumentError, "Unknown linejoin type: #{value}" unless %w[round miter bevel].include?(value.downcase)
637
600
  primitive "stroke-linejoin #{value}"
638
601
  end
639
602
 
640
603
  def stroke_miterlimit(value)
604
+ value = Float(value)
641
605
  Kernel.raise ArgumentError, 'miterlimit must be >= 1' if value < 1
642
606
  primitive "stroke-miterlimit #{value}"
643
607
  end
@@ -645,7 +609,7 @@ module Magick
645
609
  # Specify opacity of stroke drawing color
646
610
  # (use "xx%" to indicate percentage)
647
611
  def stroke_opacity(opacity)
648
- check_opacity(opacity)
612
+ opacity = to_opacity(opacity)
649
613
  primitive "stroke-opacity #{opacity}"
650
614
  end
651
615
 
@@ -656,7 +620,8 @@ module Magick
656
620
 
657
621
  # Draw text at position x,y. Add quotes to text that is not already quoted.
658
622
  def text(x, y, text)
659
- Kernel.raise ArgumentError, 'missing text argument' if text.to_s.empty?
623
+ text = to_string(text)
624
+ Kernel.raise ArgumentError, 'missing text argument' if text.empty?
660
625
  if text.length > 2 && /\A(?:\"[^\"]+\"|\'[^\']+\'|\{[^\}]+\})\z/.match(text)
661
626
  # text already quoted
662
627
  elsif !text['\'']
@@ -801,12 +766,6 @@ module Magick
801
766
  module Post_ObjectData_Descriptor
802
767
  Confirmed_ObjectData_Size = '9:10'
803
768
  end
804
-
805
- # Make all constants above immutable
806
- constants.each do |record|
807
- rec = const_get(record)
808
- rec.constants.each { |ds| rec.const_get(ds).freeze }
809
- end
810
769
  end # module Magick::IPTC
811
770
 
812
771
  # Ruby-level Magick::Image methods
@@ -1116,13 +1075,13 @@ module Magick
1116
1075
  %i[red green blue opacity].each do |c|
1117
1076
  module_eval <<-END_EVAL, __FILE__, __LINE__ + 1
1118
1077
  def #{c}
1119
- return collect { |p| p.#{c} }
1078
+ return collect { |p| p.#{c} }
1120
1079
  end
1121
1080
  def #{c}=(v)
1122
- each { |p| p.#{c} = v }
1123
- changed
1124
- notify_observers(self)
1125
- nil
1081
+ each { |p| p.#{c} = v }
1082
+ changed
1083
+ notify_observers(self)
1084
+ v
1126
1085
  end
1127
1086
  END_EVAL
1128
1087
  end
@@ -1346,17 +1305,11 @@ module Magick
1346
1305
  %w[& + - |].each do |op|
1347
1306
  module_eval <<-END_BINOPS, __FILE__, __LINE__ + 1
1348
1307
  def #{op}(other)
1308
+ assert_image_array(other)
1349
1309
  ilist = self.class.new
1350
- begin
1351
- a = other #{op} @images
1352
- rescue TypeError
1353
- Kernel.raise ArgumentError, "Magick::ImageList expected, got " + other.class.to_s
1354
- end
1310
+ a = other #{op} @images
1355
1311
  current = get_current()
1356
- a.each do |image|
1357
- assert_image image
1358
- ilist << image
1359
- end
1312
+ a.each { |image| ilist << image }
1360
1313
  ilist.set_current current
1361
1314
  return ilist
1362
1315
  end
@@ -1385,16 +1338,18 @@ module Magick
1385
1338
  # return if A.scene != B.scene
1386
1339
  # return A.length <=> B.length
1387
1340
  def <=>(other)
1388
- Kernel.raise TypeError, "#{self.class} required (#{other.class} given)" unless other.is_a? self.class
1341
+ return unless other.is_a? self.class
1342
+
1389
1343
  size = [length, other.length].min
1390
1344
  size.times do |x|
1391
1345
  r = self[x] <=> other[x]
1392
1346
  return r unless r.zero?
1393
1347
  end
1348
+
1394
1349
  return 0 if @scene.nil? && other.scene.nil?
1350
+ return if @scene.nil? && !other.scene.nil?
1351
+ return if !@scene.nil? && other.scene.nil?
1395
1352
 
1396
- Kernel.raise TypeError, "cannot convert nil into #{other.scene.class}" if @scene.nil? && !other.scene.nil?
1397
- Kernel.raise TypeError, "cannot convert nil into #{scene.class}" if !@scene.nil? && other.scene.nil?
1398
1353
  r = scene <=> other.scene
1399
1354
  return r unless r.zero?
1400
1355
 
@@ -1426,7 +1381,7 @@ module Magick
1426
1381
 
1427
1382
  %i[
1428
1383
  at each each_index empty? fetch
1429
- first hash include? index length rindex sort!
1384
+ first hash include? index length rindex
1430
1385
  ].each do |mth|
1431
1386
  module_eval <<-END_SIMPLE_DELEGATES, __FILE__, __LINE__ + 1
1432
1387
  def #{mth}(*args, &block)
@@ -1436,6 +1391,11 @@ module Magick
1436
1391
  end
1437
1392
  alias size length
1438
1393
 
1394
+ def sort!(*args, &block)
1395
+ @images.sort!(*args, &block)
1396
+ self
1397
+ end
1398
+
1439
1399
  def clear
1440
1400
  @scene = nil
1441
1401
  @images.clear
@@ -1483,7 +1443,7 @@ module Magick
1483
1443
  alias map! collect!
1484
1444
  alias __map__! collect!
1485
1445
 
1486
- # ImageMagic used affinity in 6.4.3, switch to remap in 6.4.4.
1446
+ # ImageMagick used affinity in 6.4.3, switch to remap in 6.4.4.
1487
1447
  alias affinity remap
1488
1448
 
1489
1449
  def compact
@@ -1546,7 +1506,12 @@ module Magick
1546
1506
  end
1547
1507
 
1548
1508
  def eql?(other)
1549
- assert_image_array other
1509
+ begin
1510
+ assert_image_array other
1511
+ rescue ArgumentError
1512
+ return false
1513
+ end
1514
+
1550
1515
  eql = other.eql?(@images)
1551
1516
  begin # "other" is another ImageList
1552
1517
  eql &&= @scene == other.scene
@@ -1650,7 +1615,9 @@ module Magick
1650
1615
  # it up the line. Catch a NameError and emit a useful message.
1651
1616
  def method_missing(meth_id, *args, &block)
1652
1617
  if @scene
1653
- @images[@scene].send(meth_id, *args, &block)
1618
+ img = @images[@scene]
1619
+ new_img = img.send(meth_id, *args, &block)
1620
+ img.object_id == new_img.object_id ? self : new_img
1654
1621
  else
1655
1622
  super
1656
1623
  end
@@ -1837,7 +1804,6 @@ module Magick
1837
1804
  end
1838
1805
 
1839
1806
  def values_at(*args)
1840
- a = @images.values_at(*args)
1841
1807
  a = self.class.new
1842
1808
  @images.values_at(*args).each { |image| a << image }
1843
1809
  a.scene = a.length - 1
@@ -1888,7 +1854,7 @@ module Magick
1888
1854
  class HatchFill
1889
1855
  def initialize(bgcolor, hatchcolor = 'white', dist = 10)
1890
1856
  @bgcolor = bgcolor
1891
- @hatchpixel = Pixel.from_color(hatchcolor)
1857
+ @hatchpixel = hatchcolor.is_a?(Pixel) ? hatchcolor : Pixel.from_color(hatchcolor)
1892
1858
  @dist = dist
1893
1859
  end
1894
1860
 
@@ -162,6 +162,8 @@ module Magick
162
162
  (@width - @image.columns * scale) / 2.0
163
163
  when /\AxMax/
164
164
  @width - @image.columns * scale
165
+ else
166
+ 0
165
167
  end
166
168
 
167
169
  ty = case @align
@@ -171,6 +173,8 @@ module Magick
171
173
  (@height - @image.rows * scale) / 2.0
172
174
  when /YMax\z/
173
175
  @height - @image.rows * scale
176
+ else
177
+ 0
174
178
  end
175
179
  [tx, ty]
176
180
  end
@@ -182,7 +186,7 @@ module Magick
182
186
  width = @width
183
187
  height = @height
184
188
  elsif @meet_or_slice == 'meet'
185
- scale = [@width / @image.columns, @height / @image.rows].min
189
+ scale = [@width / @image.columns, @height / @image.rows].min || 1.0
186
190
  width = @image.columns
187
191
  height = @image.rows
188
192
  else
@@ -193,7 +197,7 @@ module Magick
193
197
  end
194
198
 
195
199
  gc.clip_path(name)
196
- scale = [@width / @image.columns, @height / @image.rows].max
200
+ scale = [@width / @image.columns, @height / @image.rows].max || 1.0
197
201
  width = @image.columns
198
202
  height = @image.rows
199
203
  end
data/lib/rvg/misc.rb CHANGED
@@ -452,10 +452,10 @@ module Magick
452
452
  }
453
453
 
454
454
  FONT_WEIGHT = {
455
- 'normal' => Magick::NormalWeight,
456
- 'bold' => Magick::BoldWeight,
457
- 'bolder' => Magick::BolderWeight,
458
- 'lighter' => Magick::LighterWeight
455
+ normal: Magick::NormalWeight,
456
+ bold: Magick::BoldWeight,
457
+ bolder: Magick::BolderWeight,
458
+ lighter: Magick::LighterWeight
459
459
  }
460
460
 
461
461
  TEXT_ANCHOR = {
@@ -579,7 +579,7 @@ module Magick
579
579
 
580
580
  def font_weight(weight)
581
581
  # If the arg is not in the hash use it directly. Handles numeric values.
582
- weight = FONT_WEIGHT.fetch(weight) { |key| key }
582
+ weight = weight.is_a?(Numeric) ? weight : FONT_WEIGHT.fetch(weight.to_sym, Magick::NormalWeight)
583
583
  @gc.font_weight(weight)
584
584
  @shadow[-1].font_weight = weight
585
585
  nil
@@ -646,7 +646,7 @@ module Magick
646
646
 
647
647
  def skewX(degrees)
648
648
  degrees = Magick::RVG.convert_one_to_float(degrees)
649
- @gc.skewX(degrees)
649
+ @gc.skewx(degrees)
650
650
  @ry = Math.tan(GraphicContext.degrees_to_radians(degrees))
651
651
  concat_matrix
652
652
  nil
@@ -654,7 +654,7 @@ module Magick
654
654
 
655
655
  def skewY(degrees)
656
656
  degrees = Magick::RVG.convert_one_to_float(degrees)
657
- @gc.skewY(degrees)
657
+ @gc.skewy(degrees)
658
658
  @rx = Math.tan(GraphicContext.degrees_to_radians(degrees))
659
659
  concat_matrix
660
660
  nil
data/lib/rvg/rvg.rb CHANGED
@@ -90,6 +90,8 @@ module Magick
90
90
  end
91
91
  bg_image
92
92
  end
93
+ else
94
+ @background_image.copy
93
95
  end
94
96
  else
95
97
  @background_image.copy
@@ -137,8 +137,8 @@ module Magick
137
137
  rescue ArgumentError
138
138
  raise ArgumentError, "arguments must be convertable to float (got #{x.class}, #{y.class}, #{width.class}, #{height.class})"
139
139
  end
140
- raise(ArgumentError, "viewbox width must be > 0 (#{width} given)") unless width >= 0
141
- raise(ArgumentError, "viewbox height must be > 0 (#{height} given)") unless height >= 0
140
+ raise(ArgumentError, "viewbox width must be > 0 (#{@vbx_width} given)") unless @vbx_width >= 0
141
+ raise(ArgumentError, "viewbox height must be > 0 (#{@vbx_height} given)") unless @vbx_height >= 0
142
142
 
143
143
  # return the user-coordinate space attributes if defined
144
144
  class << self
@@ -89,7 +89,7 @@ module Magick
89
89
  cx = Float(args[0])
90
90
  cy = Float(args[1])
91
91
  @transforms << [:translate, [cx, cy]]
92
- @transforms << [:rotate, [angle]]
92
+ @transforms << [:rotate, [Float(angle)]]
93
93
  @transforms << [:translate, [-cx, -cy]]
94
94
  else
95
95
  raise ArgumentError, "wrong number of arguments (#{args.length} for 1 or 3)"
data/rmagick.gemspec CHANGED
@@ -14,27 +14,16 @@ Gem::Specification.new do |s|
14
14
  s.license = 'MIT'
15
15
 
16
16
  tracked_files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
17
- file_exclusion_regex = %r{\A(doc|benchmarks|examples|spec|lib/rvg/to_c.rb)}
18
- files = tracked_files.reject { |file| file[file_exclusion_regex] }
19
- test_files = files.grep(%r{^(test|spec|features)/})
17
+ file_exclusion_regex = /\A(doc|benchmarks|examples|spec|Steepfile)/
18
+ files = tracked_files.reject { |file| file[file_exclusion_regex] }
20
19
 
21
- s.files = files
22
- s.test_files = test_files
23
- s.require_paths << 'ext' << 'deprecated'
20
+ s.files = files
21
+ s.require_paths << 'ext'
24
22
 
25
23
  s.extensions = %w[ext/RMagick/extconf.rb]
26
24
  s.required_ruby_version = ">= #{Magick::MIN_RUBY_VERSION}"
27
25
  s.requirements << "ImageMagick #{Magick::MIN_IM_VERSION} or later"
28
26
 
29
- s.add_development_dependency 'pry', '~> 0.14'
30
- s.add_development_dependency 'rake-compiler', '~> 1.0'
31
- s.add_development_dependency 'rspec', '~> 3.8'
32
- s.add_development_dependency 'rspec_junit_formatter', '~> 0.4.1'
33
- if RUBY_PLATFORM !~ /mswin|mingw/
34
- s.add_development_dependency 'rubocop', '~> 0.81.0'
35
- s.add_development_dependency 'rubocop-rspec', '~> 1.38.1'
36
- s.add_development_dependency 'rubocop-performance', '~> 1.5.2'
37
- end
38
- s.add_development_dependency 'simplecov', '~> 0.16.1'
39
- s.add_development_dependency 'yard', '~> 0.9.24'
27
+ s.add_runtime_dependency 'pkg-config', '~> 1.4'
28
+ s.add_runtime_dependency 'observer', '~> 0.1'
40
29
  end
@@ -0,0 +1,64 @@
1
+ module Magick
2
+ interface _DrawCommonMethods
3
+ def affine: (magick_real sx, magick_real rx, magick_real ry, magick_real sy, magick_real tx, magick_real ty) -> self
4
+ def alpha: (magick_real x, magick_real y, PaintMethod method) -> self
5
+ def arc: (magick_real start_x, magick_real start_y, magick_real end_x, magick_real end_y, magick_real start_degrees, magick_real end_degrees) -> self
6
+ def bezier: (*magick_real points) -> self
7
+ def circle: (magick_real origin_x, magick_real origin_y, magick_real perim_x, magick_real perim_y) -> self
8
+ def clip_path: (interned name) -> self
9
+ def clip_rule: (interned rule) -> self
10
+ def clip_units: (interned unit) -> self
11
+ def color: (magick_real x, magick_real y, PaintMethod method) -> self
12
+ def decorate: (DecorationType decoration) -> self
13
+ def define_clip_path: (interned name) { () -> void } -> void
14
+ def ellipse: (magick_real origin_x, magick_real origin_y, magick_real width, magick_real height, magick_real arc_start, magick_real arc_end) -> self
15
+ def encoding: (interned encoding) -> self
16
+ def fill: (interned colorspec) -> self
17
+ alias fill_color fill
18
+ alias fill_pattern fill
19
+ def fill_opacity: (magick_percentage opacity) -> self
20
+ def fill_rule: (interned rule) -> self
21
+ def gravity: (GravityType grav) -> self
22
+ def image: (CompositeOperator composite, magick_real x, magick_real y, magick_real width, magick_real height, String image_file_path) -> self
23
+ def interline_spacing: (magick_real space) -> self
24
+ def interword_spacing: (magick_real space) -> self
25
+ def kerning: (magick_real space) -> self
26
+ def line: (magick_real start_x, magick_real start_y, magick_real end_x, magick_real end_y) -> self
27
+ def opacity: (magick_percentage opacity) -> self
28
+ def path: (interned cmds) -> self
29
+ def pattern: (interned name, magick_real x, magick_real y, magick_real width, magick_real height) { () -> void } -> void
30
+ def point: (magick_real x, magick_real y) -> self
31
+ def pointsize: (magick_real points) -> self
32
+ def polygon: (*magick_real points) -> self
33
+ def polyline: (*magick_real points) -> self
34
+ def rectangle: (magick_real upper_left_x, magick_real upper_left_y, magick_real lower_right_x, magick_real lower_right_y) -> self
35
+ def roundrectangle: (magick_real center_x, magick_real center_y, magick_real width, magick_real height, magick_real corner_width, magick_real corner_height) -> self
36
+ def skewx: (magick_real angle) -> self
37
+ def skewy: (magick_real angle) -> self
38
+ def stroke: (interned colorspec) -> self
39
+ alias stroke_color stroke
40
+ alias stroke_pattern stroke
41
+ def stroke_antialias: (bool `bool`) -> self
42
+ def stroke_dasharray: (*magick_real list) -> self
43
+ def stroke_dashoffset: (?magick_real value) -> self
44
+ def stroke_linecap: (interned value) -> self
45
+ def stroke_linejoin: (interned value) -> self
46
+ def stroke_miterlimit: (magick_real value) -> self
47
+ def stroke_opacity: (magick_percentage opacity) -> self
48
+ def text_align: (AlignType alignment) -> self
49
+ def text_antialias: (bool boolean) -> self
50
+ def text_undercolor: (String color) -> self
51
+
52
+ def annotate: (magick_image image_arg, int width_arg, int height_arg, int x_arg, int y_arg, string text) -> self
53
+ | (magick_image image_arg, int width_arg, int height_arg, int x_arg, int y_arg, string text) { (self) -> void } -> self
54
+ def composite: (magick_real x, magick_real y, magick_real width, magick_real height, magick_image image, ?CompositeOperator composite_op) -> self
55
+ def draw: (magick_image image_arg) -> self
56
+ def get_type_metrics: (magick_image image, string text) -> TypeMetric
57
+ | (string text) -> TypeMetric
58
+ def get_multiline_type_metrics: (magick_image image, string text) -> TypeMetric
59
+ | (string text) -> TypeMetric
60
+ def marshal_dump: () -> Hash[Symbol, untyped]
61
+ def marshal_load: (Hash[Symbol, untyped] ddraw) -> self
62
+ def primitive: (string primitive) -> self
63
+ end
64
+ end