rmagick 4.2.5 → 5.5.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -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.5'
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'