rmagick 4.2.6 → 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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/ImageMagick6/devcontainer.json +1 -1
  3. data/.devcontainer/{ImageMagick7/devcontainer.json → devcontainer.json} +2 -2
  4. data/.devcontainer/setup-user.sh +1 -1
  5. data/.editorconfig +1 -1
  6. data/.github/workflows/ci.yml +87 -9
  7. data/.gitignore +4 -0
  8. data/.rubocop_todo.yml +16 -9
  9. data/.yardopts +1 -1
  10. data/CHANGELOG.md +130 -0
  11. data/Gemfile +20 -0
  12. data/README.md +10 -17
  13. data/Rakefile +63 -80
  14. data/before_install_linux.sh +3 -3
  15. data/before_install_osx.sh +6 -5
  16. data/ext/RMagick/extconf.rb +112 -52
  17. data/ext/RMagick/{rmagick.c → rmagick.cpp} +19 -22
  18. data/ext/RMagick/rmagick.h +88 -59
  19. data/ext/RMagick/rmagick_gvl.h +224 -0
  20. data/ext/RMagick/{rmdraw.c → rmdraw.cpp} +170 -159
  21. data/ext/RMagick/{rmenum.c → rmenum.cpp} +69 -50
  22. data/ext/RMagick/{rmfill.c → rmfill.cpp} +85 -24
  23. data/ext/RMagick/{rmilist.c → rmilist.cpp} +191 -93
  24. data/ext/RMagick/{rmimage.c → rmimage.cpp} +1543 -989
  25. data/ext/RMagick/{rminfo.c → rminfo.cpp} +140 -152
  26. data/ext/RMagick/{rmkinfo.c → rmkinfo.cpp} +46 -34
  27. data/ext/RMagick/rmmain.cpp +1923 -0
  28. data/ext/RMagick/{rmmontage.c → rmmontage.cpp} +50 -29
  29. data/ext/RMagick/{rmpixel.c → rmpixel.cpp} +108 -83
  30. data/ext/RMagick/{rmstruct.c → rmstruct.cpp} +6 -6
  31. data/ext/RMagick/{rmutil.c → rmutil.cpp} +62 -161
  32. data/lib/rmagick/version.rb +3 -1
  33. data/lib/rmagick.rb +2 -0
  34. data/lib/rmagick_internal.rb +76 -110
  35. data/lib/rvg/embellishable.rb +6 -2
  36. data/lib/rvg/misc.rb +7 -7
  37. data/lib/rvg/rvg.rb +2 -0
  38. data/lib/rvg/stretchable.rb +2 -2
  39. data/lib/rvg/transformable.rb +1 -1
  40. data/rmagick.gemspec +4 -13
  41. data/sig/rmagick/_draw_common_methods.rbs +64 -0
  42. data/sig/rmagick/_image_common_methods.rbs +389 -0
  43. data/sig/rmagick/draw.rbs +38 -0
  44. data/sig/rmagick/draw_attribute.rbs +28 -0
  45. data/sig/rmagick/enum.rbs +814 -0
  46. data/sig/rmagick/error.rbs +11 -0
  47. data/sig/rmagick/fill.rbs +21 -0
  48. data/sig/rmagick/geometry.rbs +14 -0
  49. data/sig/rmagick/image.rbs +194 -0
  50. data/sig/rmagick/image_list.rbs +181 -0
  51. data/sig/rmagick/iptc.rbs +101 -0
  52. data/sig/rmagick/kernel_info.rbs +12 -0
  53. data/sig/rmagick/optional_method_arguments.rbs +10 -0
  54. data/sig/rmagick/pixel.rbs +46 -0
  55. data/sig/rmagick/struct.rbs +90 -0
  56. data/sig/rmagick.rbs +43 -0
  57. data/sig/rvg/clippath.rbs +34 -0
  58. data/sig/rvg/container.rbs +78 -0
  59. data/sig/rvg/deep_equal.rbs +48 -0
  60. data/sig/rvg/describable.rbs +30 -0
  61. data/sig/rvg/embellishable.rbs +226 -0
  62. data/sig/rvg/misc.rbs +145 -0
  63. data/sig/rvg/paint.rbs +55 -0
  64. data/sig/rvg/pathdata.rbs +77 -0
  65. data/sig/rvg/rvg.rbs +125 -0
  66. data/sig/rvg/stretchable.rbs +56 -0
  67. data/sig/rvg/stylable.rbs +66 -0
  68. data/sig/rvg/text.rbs +118 -0
  69. data/sig/rvg/transformable.rbs +59 -0
  70. data/sig/rvg/units.rbs +33 -0
  71. metadata +59 -129
  72. data/.codeclimate.yml +0 -63
  73. data/deprecated/RMagick.rb +0 -6
  74. data/ext/RMagick/rmmain.c +0 -1951
@@ -5,8 +5,8 @@
5
5
  *
6
6
  * Changes since Nov. 2009 copyright © by Benjamin Thomas and Omer Bar-or
7
7
  *
8
- * @file rmutil.c
9
- * @version $Id: rmutil.c,v 1.182 2009/12/21 10:34:58 baror Exp $
8
+ * @file rmutil.cpp
9
+ * @version $Id: rmutil.cpp,v 1.182 2009/12/21 10:34:58 baror Exp $
10
10
  * @author Tim Hunter
11
11
  ******************************************************************************/
12
12
 
@@ -22,6 +22,9 @@ static VALUE rescue_not_str(VALUE, VALUE ATTRIBUTE_UNUSED) ATTRIBUTE_NORETURN;
22
22
  static void handle_exception(ExceptionInfo *, Image *, ErrorRetention);
23
23
 
24
24
 
25
+ DEFINE_GVL_STUB5(CloneImage, const Image *, const size_t, const size_t, const MagickBooleanType, ExceptionInfo *);
26
+
27
+
25
28
  /**
26
29
  * ImageMagick safe version of malloc.
27
30
  *
@@ -249,7 +252,7 @@ rm_check_ary_type(VALUE ary)
249
252
  VALUE checked = rb_check_array_type(ary);
250
253
  if (NIL_P(checked))
251
254
  {
252
- rb_raise(rb_eTypeError, "wrong argument type %"RMIsVALUE" was given. (must respond to :to_ary)", rb_obj_class(ary));
255
+ rb_raise(rb_eTypeError, "wrong argument type %" RMIsVALUE " was given. (must respond to :to_ary)", rb_obj_class(ary));
253
256
  }
254
257
  return checked;
255
258
  }
@@ -269,7 +272,7 @@ rm_check_destroyed(VALUE obj)
269
272
  {
270
273
  Image *image;
271
274
 
272
- Data_Get_Struct(obj, Image, image);
275
+ TypedData_Get_Struct(obj, Image, &rm_image_data_type, image);
273
276
  if (!image)
274
277
  {
275
278
  rb_raise(Class_DestroyedImageError, "destroyed image");
@@ -316,16 +319,16 @@ rm_no_freeze(VALUE obj)
316
319
  * No Ruby usage (internal function)
317
320
  *
318
321
  * @param str the Ruby string
319
- * @param len pointer to a long in which to store the number of characters
322
+ * @param len pointer to a size_t in which to store the number of characters
320
323
  * @return a C string version of str
321
324
  */
322
325
  char *
323
- rm_str2cstr(VALUE str, long *len)
326
+ rm_str2cstr(VALUE str, size_t *len)
324
327
  {
325
328
  StringValue(str);
326
329
  if (len)
327
330
  {
328
- *len = RSTRING_LEN(str);
331
+ *len = (size_t)RSTRING_LEN(str);
329
332
  }
330
333
  return RSTRING_PTR(str);
331
334
  }
@@ -357,49 +360,23 @@ rescue_not_str(VALUE arg, VALUE raised_exc ATTRIBUTE_UNUSED)
357
360
  *
358
361
  * @param arg the argument
359
362
  * @param max the maximum allowed value
363
+ * @param only_positive Accept whether only positive numbers?
360
364
  * @return a double
361
365
  */
362
366
  double
363
- rm_percentage(VALUE arg, double max)
367
+ rm_percentage2(VALUE arg, double max, bool only_positive)
364
368
  {
365
369
  double pct;
366
370
  char *end;
367
371
 
368
372
  if (!rm_check_num2dbl(arg))
369
373
  {
370
- char *pct_str;
371
- long pct_long;
372
-
373
- arg = rb_rescue(rb_str_to_str, arg, rescue_not_str, arg);
374
- pct_str = StringValueCStr(arg);
375
- errno = 0;
376
- pct_long = strtol(pct_str, &end, 10);
377
- if (errno == ERANGE)
378
- {
379
- rb_raise(rb_eRangeError, "`%s' out of range", pct_str);
380
- }
381
- if (*end != '\0' && *end != '%')
382
- {
383
- rb_raise(rb_eArgError, "expected percentage, got `%s'", pct_str);
384
- }
385
-
386
- if (*end == '%' && pct_long != 0)
387
- {
388
- pct = (((double)pct_long) / 100.0) * max;
389
- }
390
- else
391
- {
392
- pct = (double) pct_long;
393
- }
394
- if (pct < 0.0)
395
- {
396
- rb_raise(rb_eArgError, "percentages may not be negative (got `%s')", pct_str);
397
- }
374
+ pct = rm_str_to_pct(arg, only_positive) * max;
398
375
  }
399
376
  else
400
377
  {
401
378
  pct = NUM2DBL(arg);
402
- if (pct < 0.0)
379
+ if (pct < 0.0 && only_positive)
403
380
  {
404
381
  rb_raise(rb_eArgError, "percentages may not be negative (got `%g')", pct);
405
382
  }
@@ -409,6 +386,24 @@ rm_percentage(VALUE arg, double max)
409
386
  }
410
387
 
411
388
 
389
+ /**
390
+ * Return a double between 0.0 and max (the second argument), inclusive. If the
391
+ * argument is a number convert to a Float object, otherwise it's supposed to be
392
+ * a string in the form * "NN%". Convert to a number and then to a Float.
393
+ *
394
+ * No Ruby usage (internal function)
395
+ *
396
+ * @param arg the argument
397
+ * @param max the maximum allowed value
398
+ * @return a double
399
+ */
400
+ double
401
+ rm_percentage(VALUE arg, double max)
402
+ {
403
+ return rm_percentage2(arg, max, true);
404
+ }
405
+
406
+
412
407
  /**
413
408
  * Return 0 if rb_num2dbl doesn't raise an exception.
414
409
  *
@@ -451,7 +446,7 @@ rescue_not_dbl(VALUE ignored ATTRIBUTE_UNUSED, VALUE raised_exc ATTRIBUTE_UNUSED
451
446
  int
452
447
  rm_check_num2dbl(VALUE obj)
453
448
  {
454
- return FIX2INT(rb_rescue(check_num2dbl, obj, rescue_not_dbl, (VALUE)0));
449
+ return FIX2INT(rb_rescue(RESCUE_FUNC(check_num2dbl), obj, RESCUE_EXCEPTION_HANDLER_FUNC(rescue_not_dbl), (VALUE)0));
455
450
  }
456
451
 
457
452
 
@@ -461,15 +456,16 @@ rm_check_num2dbl(VALUE obj)
461
456
  * No Ruby usage (internal function)
462
457
  *
463
458
  * @param str the string
459
+ * @param only_positive Accept whether only positive numbers?
464
460
  * @return a double
465
461
  */
466
462
  double
467
- rm_str_to_pct(VALUE str)
463
+ rm_str_to_pct(VALUE str, bool only_positive)
468
464
  {
469
465
  long pct;
470
466
  char *pct_str, *end;
471
467
 
472
- str = rb_rescue(rb_str_to_str, str, rescue_not_str, str);
468
+ str = rb_rescue(RESCUE_FUNC(rb_str_to_str), str, RESCUE_EXCEPTION_HANDLER_FUNC(rescue_not_str), str);
473
469
  pct_str = StringValueCStr(str);
474
470
  errno = 0;
475
471
  pct = strtol(pct_str, &end, 10);
@@ -482,7 +478,7 @@ rm_str_to_pct(VALUE str)
482
478
  {
483
479
  rb_raise(rb_eArgError, "expected percentage, got `%s'", pct_str);
484
480
  }
485
- if (pct < 0L)
481
+ if (pct < 0L && only_positive)
486
482
  {
487
483
  rb_raise(rb_eArgError, "percentages may not be negative (got `%s')", pct_str);
488
484
  }
@@ -505,45 +501,7 @@ rm_str_to_pct(VALUE str)
505
501
  double
506
502
  rm_fuzz_to_dbl(VALUE fuzz_arg)
507
503
  {
508
- double fuzz;
509
- char *end;
510
-
511
- if (!rm_check_num2dbl(fuzz_arg))
512
- {
513
- char *fuzz_str;
514
-
515
- // Convert to string, issue error message if failure.
516
- fuzz_arg = rb_rescue(rb_str_to_str, fuzz_arg, rescue_not_str, fuzz_arg);
517
- fuzz_str = StringValueCStr(fuzz_arg);
518
- errno = 0;
519
- fuzz = strtod(fuzz_str, &end);
520
- if (errno == ERANGE)
521
- {
522
- rb_raise(rb_eRangeError, "`%s' out of range", fuzz_str);
523
- }
524
- if(*end == '%')
525
- {
526
- if (fuzz < 0.0)
527
- {
528
- rb_raise(rb_eArgError, "percentages may not be negative (got `%s')", fuzz_str);
529
- }
530
- fuzz = (fuzz * QuantumRange) / 100.0;
531
- }
532
- else if(*end != '\0')
533
- {
534
- rb_raise(rb_eArgError, "expected percentage, got `%s'", fuzz_str);
535
- }
536
- }
537
- else
538
- {
539
- fuzz = NUM2DBL(fuzz_arg);
540
- if (fuzz < 0.0)
541
- {
542
- rb_raise(rb_eArgError, "fuzz may not be negative (got `%g')", fuzz);
543
- }
544
- }
545
-
546
- return fuzz;
504
+ return rm_percentage(fuzz_arg, QuantumRange);
547
505
  }
548
506
 
549
507
 
@@ -780,7 +738,7 @@ rm_write_temp_image(Image *image, char *temp_name, size_t temp_name_l)
780
738
  snprintf(temp_name, temp_name_l, "mpri:%d", id);
781
739
 
782
740
  // Omit "mpri:" from filename to form the key
783
- okay = SetImageRegistry(ImageRegistryType, temp_name+5, image, exception);
741
+ okay = (MagickBooleanType)SetImageRegistry(ImageRegistryType, temp_name+5, image, exception);
784
742
  CHECK_EXCEPTION();
785
743
  DestroyExceptionInfo(exception);
786
744
  if (!okay)
@@ -908,7 +866,7 @@ ImageMagickError_initialize(int argc, VALUE *argv, VALUE self)
908
866
  }
909
867
 
910
868
  rb_call_super(super_argc, (const VALUE *)super_argv);
911
- rb_iv_set(self, "@"MAGICK_LOC, extra);
869
+ rb_iv_set(self, "@" MAGICK_LOC, extra);
912
870
 
913
871
  RB_GC_GUARD(extra);
914
872
 
@@ -1025,15 +983,7 @@ rm_get_optional_arguments(VALUE img)
1025
983
  argv[0] = img;
1026
984
  opt_args = rb_class_new_instance(1, argv, optional_method_arguments);
1027
985
 
1028
- if (rb_proc_arity(rb_block_proc()) == 0)
1029
- {
1030
- rb_warn("passing a block without an image argument is deprecated");
1031
- rb_obj_instance_eval(0, NULL, opt_args);
1032
- }
1033
- else
1034
- {
1035
- rb_yield(opt_args);
1036
- }
986
+ rb_yield(opt_args);
1037
987
  }
1038
988
 
1039
989
  RB_GC_GUARD(optional_method_arguments);
@@ -1267,13 +1217,18 @@ void rm_sync_image_options(Image *image, Info *info)
1267
1217
  }
1268
1218
 
1269
1219
  copy_options(image, info);
1220
+
1221
+ #if defined(IMAGEMAGICK_7)
1222
+ // The value of info->compression is referenced when saving the image in ImageMagick 7.
1223
+ info->compression = image->compression;
1224
+ #endif
1270
1225
  }
1271
1226
 
1272
1227
 
1273
1228
  /**
1274
1229
  * Replicate old (ImageMagick < 6.3.2) EXIF:* functionality using
1275
1230
  * GetImageProperty by returning the exif entries as a single string, separated
1276
- * by \n's. Do this so that RMagick.rb works no matter which version of
1231
+ * by \n's. Do this so that RMagick works no matter which version of
1277
1232
  * ImageMagick is in use.
1278
1233
  *
1279
1234
  * No Ruby usage (internal function)
@@ -1337,7 +1292,7 @@ rm_exif_by_entry(Image *image)
1337
1292
  return Qnil;
1338
1293
  }
1339
1294
 
1340
- str = xmalloc(len);
1295
+ str = (char *)xmalloc(len);
1341
1296
  len = 0;
1342
1297
 
1343
1298
  // Copy the exif properties and values into the string.
@@ -1392,7 +1347,7 @@ rm_exif_by_entry(Image *image)
1392
1347
  /**
1393
1348
  * Replicate old (ImageMagick < 6.3.2) EXIF:! functionality using
1394
1349
  * GetImageProperty by returning the exif entries as a single string, separated
1395
- * by \n's. Do this so that RMagick.rb works no matter which version of
1350
+ * by \n's. Do this so that RMagick works no matter which version of
1396
1351
  * ImageMagick is in use.
1397
1352
  *
1398
1353
  * No Ruby usage (internal function)
@@ -1455,7 +1410,7 @@ rm_exif_by_number(Image *image)
1455
1410
  return Qnil;
1456
1411
  }
1457
1412
 
1458
- str = xmalloc(len);
1413
+ str = (char *)xmalloc(len);
1459
1414
  len = 0;
1460
1415
 
1461
1416
  // Copy the exif properties and values into the string.
@@ -1526,7 +1481,8 @@ rm_clone_image(Image *image)
1526
1481
  ExceptionInfo *exception;
1527
1482
 
1528
1483
  exception = AcquireExceptionInfo();
1529
- clone = CloneImage(image, 0, 0, MagickTrue, exception);
1484
+ GVL_STRUCT_TYPE(CloneImage) args = { image, 0, 0, MagickTrue, exception };
1485
+ clone = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(CloneImage), &args);
1530
1486
  if (!clone)
1531
1487
  {
1532
1488
  rb_raise(rb_eNoMemError, "not enough memory to continue");
@@ -1538,64 +1494,6 @@ rm_clone_image(Image *image)
1538
1494
  }
1539
1495
 
1540
1496
 
1541
- /**
1542
- * SetImage(Info)ProgressMonitor exit.
1543
- *
1544
- * No Ruby usage (internal function)
1545
- *
1546
- * Notes:
1547
- * - ImageMagick's "tag" argument is unused. We pass along the method name
1548
- * instead.
1549
- *
1550
- * @param tag ImageMagick argument (unused)
1551
- * @param of the offset type
1552
- * @param sp the size type
1553
- * @param client_data pointer to the progress method to call
1554
- * @return true if calling client_data returns a non-nil value, otherwise false
1555
- */
1556
- MagickBooleanType
1557
- rm_progress_monitor(
1558
- const char *tag ATTRIBUTE_UNUSED,
1559
- const MagickOffsetType of,
1560
- const MagickSizeType sp,
1561
- void *client_data)
1562
- {
1563
- VALUE rval;
1564
- VALUE method, offset, span;
1565
-
1566
- // Check running thread.
1567
- if (rm_current_thread_id() != rm_main_thread_id)
1568
- {
1569
- // ImageMagick might call back in a different thread than Ruby is running in.
1570
- // If it is a different thread, it would not have a Ruby GVL and
1571
- // it could not retrieve properly Ruby stack.
1572
-
1573
- // Unfortunately, there is no API available to check if the current thread has a GVL,
1574
- // so the thread id was checked in here.
1575
- return MagickTrue;
1576
- }
1577
-
1578
- #if defined(HAVE_LONG_LONG) // defined in Ruby's defines.h
1579
- offset = rb_ll2inum(of);
1580
- span = rb_ull2inum(sp);
1581
- #else
1582
- offset = rb_int2big((long)of);
1583
- span = rb_uint2big((unsigned long)sp);
1584
- #endif
1585
-
1586
- method = rb_id2str(rb_frame_this_func());
1587
-
1588
- rval = rb_funcall((VALUE)client_data, rm_ID_call, 3, method, offset, span);
1589
-
1590
- RB_GC_GUARD(rval);
1591
- RB_GC_GUARD(method);
1592
- RB_GC_GUARD(offset);
1593
- RB_GC_GUARD(span);
1594
-
1595
- return RTEST(rval) ? MagickTrue : MagickFalse;
1596
- }
1597
-
1598
-
1599
1497
  /**
1600
1498
  * Remove the ImageMagick links between images in an scene sequence.
1601
1499
  *
@@ -1903,18 +1801,21 @@ rm_raise_exception(ExceptionInfo *exception)
1903
1801
  }
1904
1802
 
1905
1803
  /**
1906
- * Get current thread id.
1804
+ * Get IO path.
1907
1805
  *
1908
1806
  * No Ruby usage (internal function)
1909
1807
  *
1910
- * @return thread id
1808
+ * @param io An IO object
1809
+ * @return string of the path
1911
1810
  */
1912
- unsigned long long
1913
- rm_current_thread_id()
1811
+ VALUE
1812
+ rm_io_path(VALUE io)
1914
1813
  {
1915
- #if defined(_WIN32)
1916
- return (unsigned long long)GetCurrentThreadId();
1814
+ #ifdef HAVE_RB_IO_PATH
1815
+ return rb_io_path(io);
1917
1816
  #else
1918
- return (unsigned long long)pthread_self();
1817
+ rb_io_t *fptr;
1818
+ GetOpenFile(io, fptr);
1819
+ return fptr->pathv;
1919
1820
  #endif
1920
1821
  }
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Magick
2
- VERSION = '4.2.6'
4
+ VERSION = '5.5.0'
3
5
  MIN_RUBY_VERSION = '2.3.0'
4
6
  MIN_IM_VERSION = '6.7.7'
5
7
  end
data/lib/rmagick.rb CHANGED
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rmagick_internal.rb'