rmagick 2.13.2 → 4.2.2

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 (380) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +63 -0
  3. data/.editorconfig +17 -0
  4. data/.github/ISSUE_TEMPLATE.md +17 -0
  5. data/.github/workflows/ci.yml +107 -0
  6. data/.gitignore +25 -0
  7. data/.rspec +2 -0
  8. data/.rubocop.yml +37 -0
  9. data/.rubocop_todo.yml +449 -0
  10. data/.yardopts +5 -0
  11. data/CHANGELOG.md +1277 -0
  12. data/CODE_OF_CONDUCT.md +128 -0
  13. data/CONTRIBUTING.md +81 -0
  14. data/Gemfile +4 -0
  15. data/LICENSE +20 -0
  16. data/README.md +324 -0
  17. data/Rakefile +190 -0
  18. data/before_install_linux.sh +69 -0
  19. data/before_install_osx.sh +57 -0
  20. data/deprecated/RMagick.rb +6 -0
  21. data/ext/RMagick/extconf.rb +334 -333
  22. data/ext/RMagick/rmagick.c +129 -127
  23. data/ext/RMagick/rmagick.h +221 -320
  24. data/ext/RMagick/rmdraw.c +458 -767
  25. data/ext/RMagick/rmenum.c +305 -752
  26. data/ext/RMagick/rmfill.c +231 -199
  27. data/ext/RMagick/rmilist.c +437 -478
  28. data/ext/RMagick/rmimage.c +6130 -5342
  29. data/ext/RMagick/rminfo.c +695 -833
  30. data/ext/RMagick/rmkinfo.c +198 -0
  31. data/ext/RMagick/rmmain.c +752 -506
  32. data/ext/RMagick/rmmontage.c +94 -152
  33. data/ext/RMagick/rmpixel.c +619 -425
  34. data/ext/RMagick/rmstruct.c +206 -309
  35. data/ext/RMagick/rmutil.c +514 -344
  36. data/lib/rmagick/version.rb +5 -0
  37. data/lib/rmagick.rb +1 -0
  38. data/lib/rmagick_internal.rb +1922 -0
  39. data/lib/rvg/clippath.rb +35 -39
  40. data/lib/rvg/container.rb +123 -124
  41. data/lib/rvg/deep_equal.rb +45 -49
  42. data/lib/rvg/describable.rb +41 -47
  43. data/lib/rvg/embellishable.rb +380 -411
  44. data/lib/rvg/misc.rb +691 -711
  45. data/lib/rvg/paint.rb +43 -47
  46. data/lib/rvg/pathdata.rb +119 -125
  47. data/lib/rvg/rvg.rb +214 -213
  48. data/lib/rvg/stretchable.rb +153 -162
  49. data/lib/rvg/stylable.rb +111 -117
  50. data/lib/rvg/text.rb +169 -180
  51. data/lib/rvg/transformable.rb +121 -127
  52. data/lib/rvg/units.rb +58 -61
  53. data/rmagick.gemspec +36 -16
  54. metadata +188 -365
  55. data/ChangeLog +0 -773
  56. data/Doxyfile +0 -1514
  57. data/README-Mac-OSX.txt +0 -1
  58. data/README.html +0 -10
  59. data/build_tarball.rake +0 -215
  60. data/doc/comtasks.html +0 -287
  61. data/doc/constants.html +0 -1581
  62. data/doc/css/doc.css +0 -299
  63. data/doc/css/popup.css +0 -34
  64. data/doc/css/ref.css +0 -67
  65. data/doc/draw.html +0 -3269
  66. data/doc/ex/InitialCoords.rb +0 -23
  67. data/doc/ex/NewCoordSys.rb +0 -32
  68. data/doc/ex/OrigCoordSys.rb +0 -18
  69. data/doc/ex/PreserveAspectRatio.rb +0 -205
  70. data/doc/ex/RotateScale.rb +0 -37
  71. data/doc/ex/Skew.rb +0 -38
  72. data/doc/ex/Use01.rb +0 -16
  73. data/doc/ex/Use02.rb +0 -21
  74. data/doc/ex/Use03.rb +0 -16
  75. data/doc/ex/ViewBox.rb +0 -33
  76. data/doc/ex/adaptive_threshold.rb +0 -10
  77. data/doc/ex/add_noise.rb +0 -17
  78. data/doc/ex/affine.rb +0 -48
  79. data/doc/ex/affine_transform.rb +0 -20
  80. data/doc/ex/arc.rb +0 -49
  81. data/doc/ex/arcpath.rb +0 -33
  82. data/doc/ex/arcs01.rb +0 -28
  83. data/doc/ex/arcs02.rb +0 -61
  84. data/doc/ex/average.rb +0 -15
  85. data/doc/ex/axes.rb +0 -64
  86. data/doc/ex/baseline_shift01.rb +0 -18
  87. data/doc/ex/bilevel_channel.rb +0 -9
  88. data/doc/ex/blur_image.rb +0 -12
  89. data/doc/ex/border.rb +0 -10
  90. data/doc/ex/bounding_box.rb +0 -44
  91. data/doc/ex/cbezier1.rb +0 -42
  92. data/doc/ex/cbezier2.rb +0 -42
  93. data/doc/ex/cbezier3.rb +0 -42
  94. data/doc/ex/cbezier4.rb +0 -43
  95. data/doc/ex/cbezier5.rb +0 -43
  96. data/doc/ex/cbezier6.rb +0 -53
  97. data/doc/ex/channel.rb +0 -26
  98. data/doc/ex/charcoal.rb +0 -12
  99. data/doc/ex/chop.rb +0 -29
  100. data/doc/ex/circle.rb +0 -33
  101. data/doc/ex/circle01.rb +0 -17
  102. data/doc/ex/clip_path.rb +0 -60
  103. data/doc/ex/coalesce.rb +0 -60
  104. data/doc/ex/color_fill_to_border.rb +0 -29
  105. data/doc/ex/color_floodfill.rb +0 -28
  106. data/doc/ex/color_histogram.rb +0 -48
  107. data/doc/ex/color_reset.rb +0 -11
  108. data/doc/ex/colorize.rb +0 -16
  109. data/doc/ex/colors.rb +0 -64
  110. data/doc/ex/compose_mask.rb +0 -23
  111. data/doc/ex/composite.rb +0 -135
  112. data/doc/ex/composite_layers.rb +0 -53
  113. data/doc/ex/composite_tiled.rb +0 -23
  114. data/doc/ex/contrast.rb +0 -36
  115. data/doc/ex/crop.rb +0 -31
  116. data/doc/ex/crop_with_gravity.rb +0 -46
  117. data/doc/ex/cubic01.rb +0 -45
  118. data/doc/ex/cubic02.rb +0 -94
  119. data/doc/ex/cycle_colormap.rb +0 -21
  120. data/doc/ex/dissolve.rb +0 -13
  121. data/doc/ex/drawcomp.rb +0 -42
  122. data/doc/ex/drop_shadow.rb +0 -60
  123. data/doc/ex/edge.rb +0 -11
  124. data/doc/ex/ellipse.rb +0 -45
  125. data/doc/ex/ellipse01.rb +0 -22
  126. data/doc/ex/emboss.rb +0 -11
  127. data/doc/ex/enhance.rb +0 -28
  128. data/doc/ex/equalize.rb +0 -11
  129. data/doc/ex/evenodd.rb +0 -43
  130. data/doc/ex/fill_pattern.rb +0 -26
  131. data/doc/ex/flatten_images.rb +0 -36
  132. data/doc/ex/flip.rb +0 -11
  133. data/doc/ex/flop.rb +0 -11
  134. data/doc/ex/font_styles.rb +0 -34
  135. data/doc/ex/fonts.rb +0 -20
  136. data/doc/ex/frame.rb +0 -12
  137. data/doc/ex/gaussian_blur.rb +0 -11
  138. data/doc/ex/get_multiline_type_metrics.rb +0 -42
  139. data/doc/ex/get_pixels.rb +0 -48
  140. data/doc/ex/get_type_metrics.rb +0 -146
  141. data/doc/ex/gradientfill.rb +0 -27
  142. data/doc/ex/grav.rb +0 -46
  143. data/doc/ex/gravity.rb +0 -79
  144. data/doc/ex/group.rb +0 -26
  145. data/doc/ex/hatchfill.rb +0 -27
  146. data/doc/ex/image.rb +0 -46
  147. data/doc/ex/images/Apple.miff +0 -0
  148. data/doc/ex/images/Ballerina.jpg +0 -0
  149. data/doc/ex/images/Ballerina3.jpg +0 -0
  150. data/doc/ex/images/Button_0.gif +0 -0
  151. data/doc/ex/images/Button_1.gif +0 -0
  152. data/doc/ex/images/Button_2.gif +0 -0
  153. data/doc/ex/images/Button_3.gif +0 -0
  154. data/doc/ex/images/Button_4.gif +0 -0
  155. data/doc/ex/images/Button_5.gif +0 -0
  156. data/doc/ex/images/Button_6.gif +0 -0
  157. data/doc/ex/images/Button_7.gif +0 -0
  158. data/doc/ex/images/Button_8.gif +0 -0
  159. data/doc/ex/images/Button_9.gif +0 -0
  160. data/doc/ex/images/Button_A.gif +0 -0
  161. data/doc/ex/images/Button_B.gif +0 -0
  162. data/doc/ex/images/Button_C.gif +0 -0
  163. data/doc/ex/images/Button_D.gif +0 -0
  164. data/doc/ex/images/Button_E.gif +0 -0
  165. data/doc/ex/images/Button_F.gif +0 -0
  166. data/doc/ex/images/Button_G.gif +0 -0
  167. data/doc/ex/images/Button_H.gif +0 -0
  168. data/doc/ex/images/Button_I.gif +0 -0
  169. data/doc/ex/images/Button_J.gif +0 -0
  170. data/doc/ex/images/Button_K.gif +0 -0
  171. data/doc/ex/images/Button_L.gif +0 -0
  172. data/doc/ex/images/Button_M.gif +0 -0
  173. data/doc/ex/images/Button_N.gif +0 -0
  174. data/doc/ex/images/Button_O.gif +0 -0
  175. data/doc/ex/images/Button_P.gif +0 -0
  176. data/doc/ex/images/Button_Q.gif +0 -0
  177. data/doc/ex/images/Button_R.gif +0 -0
  178. data/doc/ex/images/Button_S.gif +0 -0
  179. data/doc/ex/images/Button_T.gif +0 -0
  180. data/doc/ex/images/Button_U.gif +0 -0
  181. data/doc/ex/images/Button_V.gif +0 -0
  182. data/doc/ex/images/Button_W.gif +0 -0
  183. data/doc/ex/images/Button_X.gif +0 -0
  184. data/doc/ex/images/Button_Y.gif +0 -0
  185. data/doc/ex/images/Button_Z.gif +0 -0
  186. data/doc/ex/images/Cheetah.jpg +0 -0
  187. data/doc/ex/images/Coffee.wmf +0 -0
  188. data/doc/ex/images/Flower_Hat.jpg +0 -0
  189. data/doc/ex/images/Gold_Statue.jpg +0 -0
  190. data/doc/ex/images/Hot_Air_Balloons.jpg +0 -0
  191. data/doc/ex/images/Hot_Air_Balloons_H.jpg +0 -0
  192. data/doc/ex/images/Leaf.miff +0 -0
  193. data/doc/ex/images/No.wmf +0 -0
  194. data/doc/ex/images/Polynesia.jpg +0 -0
  195. data/doc/ex/images/Red_Rocks.jpg +0 -0
  196. data/doc/ex/images/Rocks_On_Beach.miff +0 -0
  197. data/doc/ex/images/Shorts.jpg +0 -0
  198. data/doc/ex/images/Snake.wmf +0 -0
  199. data/doc/ex/images/Violin.jpg +0 -0
  200. data/doc/ex/images/Yellow_Rose.miff +0 -0
  201. data/doc/ex/images/big-duck.gif +0 -0
  202. data/doc/ex/images/duck.gif +0 -0
  203. data/doc/ex/images/duck0.gif +0 -0
  204. data/doc/ex/images/duck1.gif +0 -0
  205. data/doc/ex/images/duck10.gif +0 -0
  206. data/doc/ex/images/duck11.gif +0 -0
  207. data/doc/ex/images/duck12.gif +0 -0
  208. data/doc/ex/images/duck13.gif +0 -0
  209. data/doc/ex/images/duck14.gif +0 -0
  210. data/doc/ex/images/duck15.gif +0 -0
  211. data/doc/ex/images/duck2.gif +0 -0
  212. data/doc/ex/images/duck3.gif +0 -0
  213. data/doc/ex/images/duck4.gif +0 -0
  214. data/doc/ex/images/duck5.gif +0 -0
  215. data/doc/ex/images/duck6.gif +0 -0
  216. data/doc/ex/images/duck7.gif +0 -0
  217. data/doc/ex/images/duck8.gif +0 -0
  218. data/doc/ex/images/duck9.gif +0 -0
  219. data/doc/ex/images/graydient230x6.gif +0 -0
  220. data/doc/ex/images/logo400x83.gif +0 -0
  221. data/doc/ex/images/model.miff +0 -0
  222. data/doc/ex/images/notimplemented.gif +0 -0
  223. data/doc/ex/images/smile.miff +0 -0
  224. data/doc/ex/images/spin.gif +0 -0
  225. data/doc/ex/implode.rb +0 -34
  226. data/doc/ex/level.rb +0 -11
  227. data/doc/ex/level_colors.rb +0 -11
  228. data/doc/ex/line.rb +0 -42
  229. data/doc/ex/line01.rb +0 -23
  230. data/doc/ex/mask.rb +0 -36
  231. data/doc/ex/matte_fill_to_border.rb +0 -40
  232. data/doc/ex/matte_floodfill.rb +0 -33
  233. data/doc/ex/matte_replace.rb +0 -40
  234. data/doc/ex/median_filter.rb +0 -28
  235. data/doc/ex/modulate.rb +0 -11
  236. data/doc/ex/mono.rb +0 -23
  237. data/doc/ex/morph.rb +0 -26
  238. data/doc/ex/mosaic.rb +0 -35
  239. data/doc/ex/motion_blur.rb +0 -11
  240. data/doc/ex/negate.rb +0 -11
  241. data/doc/ex/negate_channel.rb +0 -9
  242. data/doc/ex/nested_rvg.rb +0 -21
  243. data/doc/ex/nonzero.rb +0 -43
  244. data/doc/ex/normalize.rb +0 -11
  245. data/doc/ex/oil_paint.rb +0 -11
  246. data/doc/ex/opacity.rb +0 -37
  247. data/doc/ex/ordered_dither.rb +0 -11
  248. data/doc/ex/path.rb +0 -64
  249. data/doc/ex/pattern1.rb +0 -25
  250. data/doc/ex/pattern2.rb +0 -26
  251. data/doc/ex/polaroid.rb +0 -28
  252. data/doc/ex/polygon.rb +0 -24
  253. data/doc/ex/polygon01.rb +0 -23
  254. data/doc/ex/polyline.rb +0 -23
  255. data/doc/ex/polyline01.rb +0 -23
  256. data/doc/ex/posterize.rb +0 -8
  257. data/doc/ex/preview.rb +0 -9
  258. data/doc/ex/qbezierpath.rb +0 -52
  259. data/doc/ex/quad01.rb +0 -36
  260. data/doc/ex/quantize-m.rb +0 -25
  261. data/doc/ex/radial_blur.rb +0 -9
  262. data/doc/ex/raise.rb +0 -8
  263. data/doc/ex/random_threshold_channel.rb +0 -13
  264. data/doc/ex/rect01.rb +0 -15
  265. data/doc/ex/rect02.rb +0 -22
  266. data/doc/ex/rectangle.rb +0 -35
  267. data/doc/ex/reduce_noise.rb +0 -28
  268. data/doc/ex/remap.rb +0 -12
  269. data/doc/ex/remap_images.rb +0 -21
  270. data/doc/ex/resize_to_fill.rb +0 -10
  271. data/doc/ex/resize_to_fit.rb +0 -10
  272. data/doc/ex/roll.rb +0 -9
  273. data/doc/ex/rotate.rb +0 -45
  274. data/doc/ex/rotate_f.rb +0 -14
  275. data/doc/ex/roundrect.rb +0 -34
  276. data/doc/ex/rubyname.rb +0 -30
  277. data/doc/ex/rvg_clippath.rb +0 -14
  278. data/doc/ex/rvg_linecap.rb +0 -43
  279. data/doc/ex/rvg_linejoin.rb +0 -41
  280. data/doc/ex/rvg_opacity.rb +0 -19
  281. data/doc/ex/rvg_pattern.rb +0 -26
  282. data/doc/ex/rvg_stroke_dasharray.rb +0 -12
  283. data/doc/ex/segment.rb +0 -11
  284. data/doc/ex/sepiatone.rb +0 -8
  285. data/doc/ex/shade.rb +0 -11
  286. data/doc/ex/shadow.rb +0 -31
  287. data/doc/ex/shave.rb +0 -15
  288. data/doc/ex/shear.rb +0 -10
  289. data/doc/ex/sketch.rb +0 -18
  290. data/doc/ex/skewx.rb +0 -52
  291. data/doc/ex/skewy.rb +0 -47
  292. data/doc/ex/smile.rb +0 -125
  293. data/doc/ex/solarize.rb +0 -11
  294. data/doc/ex/sparse_color.rb +0 -55
  295. data/doc/ex/splice.rb +0 -9
  296. data/doc/ex/spread.rb +0 -11
  297. data/doc/ex/stegano.rb +0 -55
  298. data/doc/ex/stroke_dasharray.rb +0 -43
  299. data/doc/ex/stroke_fill.rb +0 -11
  300. data/doc/ex/stroke_linecap.rb +0 -44
  301. data/doc/ex/stroke_linejoin.rb +0 -48
  302. data/doc/ex/stroke_width.rb +0 -49
  303. data/doc/ex/swirl.rb +0 -17
  304. data/doc/ex/text.rb +0 -37
  305. data/doc/ex/text01.rb +0 -17
  306. data/doc/ex/text_align.rb +0 -36
  307. data/doc/ex/text_antialias.rb +0 -38
  308. data/doc/ex/text_styles.rb +0 -21
  309. data/doc/ex/text_undercolor.rb +0 -28
  310. data/doc/ex/texture_fill_to_border.rb +0 -34
  311. data/doc/ex/texture_floodfill.rb +0 -32
  312. data/doc/ex/texturefill.rb +0 -25
  313. data/doc/ex/threshold.rb +0 -13
  314. data/doc/ex/to_blob.rb +0 -14
  315. data/doc/ex/translate.rb +0 -39
  316. data/doc/ex/transparent.rb +0 -38
  317. data/doc/ex/transpose.rb +0 -9
  318. data/doc/ex/transverse.rb +0 -9
  319. data/doc/ex/tref01.rb +0 -25
  320. data/doc/ex/triangle01.rb +0 -16
  321. data/doc/ex/trim.rb +0 -24
  322. data/doc/ex/tspan01.rb +0 -18
  323. data/doc/ex/tspan02.rb +0 -19
  324. data/doc/ex/tspan03.rb +0 -21
  325. data/doc/ex/unsharp_mask.rb +0 -28
  326. data/doc/ex/viewex.rb +0 -35
  327. data/doc/ex/vignette.rb +0 -12
  328. data/doc/ex/watermark.rb +0 -28
  329. data/doc/ex/wave.rb +0 -9
  330. data/doc/ex/wet_floor.rb +0 -59
  331. data/doc/ex/writing_mode01.rb +0 -27
  332. data/doc/ex/writing_mode02.rb +0 -26
  333. data/doc/ilist.html +0 -2056
  334. data/doc/image1.html +0 -4680
  335. data/doc/image2.html +0 -3665
  336. data/doc/image3.html +0 -4522
  337. data/doc/imageattrs.html +0 -1638
  338. data/doc/imusage.html +0 -514
  339. data/doc/index.html +0 -416
  340. data/doc/info.html +0 -1499
  341. data/doc/magick.html +0 -565
  342. data/doc/optequiv.html +0 -2435
  343. data/doc/rvg.html +0 -975
  344. data/doc/rvgclip.html +0 -248
  345. data/doc/rvggroup.html +0 -305
  346. data/doc/rvgimage.html +0 -289
  347. data/doc/rvgpattern.html +0 -475
  348. data/doc/rvgshape.html +0 -406
  349. data/doc/rvgstyle.html +0 -270
  350. data/doc/rvgtext.html +0 -465
  351. data/doc/rvgtspan.html +0 -238
  352. data/doc/rvgtut.html +0 -530
  353. data/doc/rvguse.html +0 -145
  354. data/doc/rvgxform.html +0 -294
  355. data/doc/scripts/doc.js +0 -22
  356. data/doc/scripts/stripeTables.js +0 -23
  357. data/doc/struct.html +0 -1339
  358. data/doc/usage.html +0 -1621
  359. data/examples/constitute.rb +0 -7
  360. data/examples/crop_with_gravity.rb +0 -46
  361. data/examples/demo.rb +0 -324
  362. data/examples/describe.rb +0 -44
  363. data/examples/find_similar_region.rb +0 -34
  364. data/examples/histogram.rb +0 -325
  365. data/examples/identify.rb +0 -187
  366. data/examples/image_opacity.rb +0 -29
  367. data/examples/import_export.rb +0 -31
  368. data/examples/pattern_fill.rb +0 -38
  369. data/examples/rotating_text.rb +0 -45
  370. data/examples/spinner.rb +0 -50
  371. data/examples/thumbnail.rb +0 -65
  372. data/examples/vignette.rb +0 -79
  373. data/ext/RMagick/MANIFEST +0 -358
  374. data/lib/RMagick.rb +0 -1962
  375. data/metaconfig +0 -7
  376. data/post-clean.rb +0 -12
  377. data/post-install.rb +0 -50
  378. data/post-setup.rb +0 -254
  379. data/setup.rb +0 -1585
  380. data/uninstall.rb +0 -76
data/ext/RMagick/rmutil.c CHANGED
@@ -12,7 +12,13 @@
12
12
 
13
13
  #include "rmagick.h"
14
14
  #include <errno.h>
15
+ #if defined(_WIN32)
16
+ #include <Windows.h>
17
+ #else
18
+ #include <pthread.h>
19
+ #endif
15
20
 
21
+ static VALUE rescue_not_str(VALUE, VALUE ATTRIBUTE_UNUSED) ATTRIBUTE_NORETURN;
16
22
  static void handle_exception(ExceptionInfo *, Image *, ErrorRetention);
17
23
 
18
24
 
@@ -78,7 +84,7 @@ magick_malloc(const size_t size)
78
84
  void
79
85
  magick_free(void *ptr)
80
86
  {
81
- (void) RelinquishMagickMemory(ptr);
87
+ RelinquishMagickMemory(ptr);
82
88
  }
83
89
 
84
90
 
@@ -112,28 +118,6 @@ magick_safe_realloc(void *memory, const size_t count, const size_t quantum)
112
118
  }
113
119
 
114
120
 
115
- /**
116
- * ImageMagick version of realloc.
117
- *
118
- * No Ruby usage (internal function)
119
- *
120
- * @param ptr pointer to the existing block of memory
121
- * @param size the new size of memory to allocate
122
- * @return pointer to a block of memory
123
- */
124
- void *
125
- magick_realloc(void *ptr, const size_t size)
126
- {
127
- void *v;
128
- v = ResizeMagickMemory(ptr, size);
129
- if (!v)
130
- {
131
- rb_raise(rb_eNoMemError, "not enough memory to continue");
132
- }
133
- return v;
134
- }
135
-
136
-
137
121
  /**
138
122
  * Make a copy of a string in malloc'd memory.
139
123
  *
@@ -149,7 +133,7 @@ magick_realloc(void *ptr, const size_t size)
149
133
  void
150
134
  magick_clone_string(char **new_str, const char *str)
151
135
  {
152
- (void) CloneString(new_str, str);
136
+ CloneString(new_str, str);
153
137
  }
154
138
 
155
139
 
@@ -208,6 +192,28 @@ rm_strncasecmp(const char *s1, const char *s2, size_t n)
208
192
  }
209
193
 
210
194
 
195
+ /**
196
+ * Get string length.
197
+ *
198
+ * No Ruby usage (internal function)
199
+ *
200
+ * @param str the string
201
+ * @param strsz the maximum number of characters
202
+ * @return same as strnlen_s()
203
+ */
204
+ size_t
205
+ rm_strnlen_s(const char *str, size_t strsz)
206
+ {
207
+ size_t length = 0;
208
+ while(*str && length < strsz)
209
+ {
210
+ str++;
211
+ length++;
212
+ }
213
+ return length;
214
+ }
215
+
216
+
211
217
  /**
212
218
  * Raise exception if array too short.
213
219
  *
@@ -228,6 +234,27 @@ rm_check_ary_len(VALUE ary, long len)
228
234
  }
229
235
 
230
236
 
237
+ /**
238
+ * Raise exception if ary argument was invalid type
239
+ *
240
+ * No Ruby usage (internal function)
241
+ *
242
+ * @param ary the array
243
+ * @return the array that is converted type of argument object if needed
244
+ * @throw TypeError
245
+ */
246
+ VALUE
247
+ rm_check_ary_type(VALUE ary)
248
+ {
249
+ VALUE checked = rb_check_array_type(ary);
250
+ if (NIL_P(checked))
251
+ {
252
+ rb_raise(rb_eTypeError, "wrong argument type %"RMIsVALUE" was given. (must respond to :to_ary)", rb_obj_class(ary));
253
+ }
254
+ return checked;
255
+ }
256
+
257
+
231
258
  /**
232
259
  * Raise an error if the image has been destroyed.
233
260
  *
@@ -274,35 +301,12 @@ rm_check_frozen(VALUE obj)
274
301
  *
275
302
  * No Ruby usage (internal function)
276
303
  *
277
- * @param obj the object of the class to override
278
- * @return 0
279
- * @throw TypeError
304
+ * @raise [TypeError]
280
305
  */
281
306
  VALUE
282
307
  rm_no_freeze(VALUE obj)
283
308
  {
284
309
  rb_raise(rb_eTypeError, "can't freeze %s", rb_class2name(CLASS_OF(obj)));
285
- return (VALUE)0;
286
- }
287
-
288
-
289
- /**
290
- * Return obj.to_s, or obj if obj is already a string.
291
- *
292
- * No Ruby usage (internal function)
293
- *
294
- * @param obj a Ruby object
295
- * @return a String representation of obj
296
- */
297
- VALUE
298
- rm_to_s(VALUE obj)
299
- {
300
-
301
- if (TYPE(obj) != T_STRING)
302
- {
303
- return rb_funcall(obj, rm_ID_to_s, 0);
304
- }
305
- return obj;
306
310
  }
307
311
 
308
312
 
@@ -327,24 +331,6 @@ rm_str2cstr(VALUE str, long *len)
327
331
  }
328
332
 
329
333
 
330
- /**
331
- * Try to convert the argument to a double, raise an exception if fail.
332
- *
333
- * No Ruby usage (internal function)
334
- *
335
- * @param arg the argument
336
- * @return arg
337
- */
338
- static VALUE
339
- arg_is_number(VALUE arg)
340
- {
341
- double d;
342
- d = NUM2DBL(arg);
343
- d = d; // satisfy icc
344
- return arg;
345
- }
346
-
347
-
348
334
  /**
349
335
  * Called when `rb_str_to_str' raises an exception.
350
336
  *
@@ -355,11 +341,10 @@ arg_is_number(VALUE arg)
355
341
  * @throw TypeError
356
342
  */
357
343
  static VALUE
358
- rescue_not_str(VALUE arg)
344
+ rescue_not_str(VALUE arg, VALUE raised_exc ATTRIBUTE_UNUSED)
359
345
  {
360
346
  rb_raise(rb_eTypeError, "argument must be a number or a string in the form 'NN%%' (%s given)",
361
347
  rb_class2name(CLASS_OF(arg)));
362
- return (VALUE)0;
363
348
  }
364
349
 
365
350
 
@@ -378,17 +363,15 @@ double
378
363
  rm_percentage(VALUE arg, double max)
379
364
  {
380
365
  double pct;
381
- long pct_long;
382
- char *pct_str, *end;
383
- int not_num;
384
-
385
- // Try to convert the argument to a number. If failure, sets not_num to non-zero.
386
- (void) rb_protect(arg_is_number, arg, &not_num);
366
+ char *end;
387
367
 
388
- if (not_num)
368
+ if (!rm_check_num2dbl(arg))
389
369
  {
370
+ char *pct_str;
371
+ long pct_long;
372
+
390
373
  arg = rb_rescue(rb_str_to_str, arg, rescue_not_str, arg);
391
- pct_str = StringValuePtr(arg);
374
+ pct_str = StringValueCStr(arg);
392
375
  errno = 0;
393
376
  pct_long = strtol(pct_str, &end, 10);
394
377
  if (errno == ERANGE)
@@ -437,7 +420,7 @@ rm_percentage(VALUE arg, double max)
437
420
  static VALUE
438
421
  check_num2dbl(VALUE obj)
439
422
  {
440
- (void) rb_num2dbl(obj);
423
+ rb_num2dbl(obj);
441
424
  return INT2FIX(1);
442
425
  }
443
426
 
@@ -451,9 +434,8 @@ check_num2dbl(VALUE obj)
451
434
  * @return 0
452
435
  */
453
436
  static VALUE
454
- rescue_not_dbl(VALUE ignored)
437
+ rescue_not_dbl(VALUE ignored ATTRIBUTE_UNUSED, VALUE raised_exc ATTRIBUTE_UNUSED)
455
438
  {
456
- ignored = ignored; // defeat gcc message
457
439
  return INT2FIX(0);
458
440
  }
459
441
 
@@ -488,7 +470,7 @@ rm_str_to_pct(VALUE str)
488
470
  char *pct_str, *end;
489
471
 
490
472
  str = rb_rescue(rb_str_to_str, str, rescue_not_str, str);
491
- pct_str = StringValuePtr(str);
473
+ pct_str = StringValueCStr(str);
492
474
  errno = 0;
493
475
  pct = strtol(pct_str, &end, 10);
494
476
 
@@ -524,17 +506,15 @@ double
524
506
  rm_fuzz_to_dbl(VALUE fuzz_arg)
525
507
  {
526
508
  double fuzz;
527
- char *fuzz_str, *end;
528
- int not_num;
529
-
530
- // Try to convert the argument to a number. If failure, sets not_num to non-zero.
531
- (void) rb_protect(arg_is_number, fuzz_arg, &not_num);
509
+ char *end;
532
510
 
533
- if (not_num)
511
+ if (!rm_check_num2dbl(fuzz_arg))
534
512
  {
513
+ char *fuzz_str;
514
+
535
515
  // Convert to string, issue error message if failure.
536
516
  fuzz_arg = rb_rescue(rb_str_to_str, fuzz_arg, rescue_not_str, fuzz_arg);
537
- fuzz_str = StringValuePtr(fuzz_arg);
517
+ fuzz_str = StringValueCStr(fuzz_arg);
538
518
  errno = 0;
539
519
  fuzz = strtod(fuzz_str, &end);
540
520
  if (errno == ERANGE)
@@ -585,17 +565,43 @@ rm_fuzz_to_dbl(VALUE fuzz_arg)
585
565
  Quantum
586
566
  rm_app2quantum(VALUE obj)
587
567
  {
588
- volatile VALUE v = obj;
568
+ VALUE v = obj;
589
569
 
590
570
  if (TYPE(obj) == T_FLOAT)
591
571
  {
592
- v = rb_funcall(obj, rm_ID_to_i, 0);
572
+ v = rb_Integer(obj);
593
573
  }
594
574
 
595
575
  return NUM2QUANTUM(v);
596
576
  }
597
577
 
598
578
 
579
+ /**
580
+ * Returns a pointer to an image structure initialized to default values
581
+ *
582
+ * No Ruby usage (internal function)
583
+ *
584
+ * @param info the info
585
+ * @return the created image
586
+ */
587
+ Image *
588
+ rm_acquire_image(ImageInfo *info)
589
+ {
590
+ #if defined(IMAGEMAGICK_7)
591
+ Image *new_image;
592
+ ExceptionInfo *exception;
593
+
594
+ exception = AcquireExceptionInfo();
595
+ new_image = AcquireImage(info, exception);
596
+ CHECK_EXCEPTION();
597
+ DestroyExceptionInfo(exception);
598
+ return new_image;
599
+ #else
600
+ return AcquireImage(info);
601
+ #endif
602
+ }
603
+
604
+
599
605
  /**
600
606
  * Send the "cur_image" method to the object. If 'img' is an ImageList, then
601
607
  * cur_image is self[\@scene]. If 'img' is an image, then cur_image is simply
@@ -619,21 +625,28 @@ rm_cur_image(VALUE img)
619
625
  * No Ruby usage (internal function)
620
626
  *
621
627
  * @param image the image
622
- * @param color the color intensity as a PixelPacket
628
+ * @param color the color intensity as a PixelColor
623
629
  * @return the named color as a String
624
- * @see rm_pixelpacket_to_color_name_info
630
+ * @see rm_pixelcolor_to_color_name_info
625
631
  */
626
632
  VALUE
627
- rm_pixelpacket_to_color_name(Image *image, PixelPacket *color)
633
+ rm_pixelcolor_to_color_name(Image *image, PixelColor *color)
628
634
  {
635
+ PixelColor pp;
629
636
  char name[MaxTextExtent];
630
- ExceptionInfo exception;
637
+ ExceptionInfo *exception;
631
638
 
632
- GetExceptionInfo(&exception);
639
+ exception = AcquireExceptionInfo();
633
640
 
634
- (void) QueryColorname(image, color, X11Compliance, name, &exception);
635
- CHECK_EXCEPTION()
636
- (void) DestroyExceptionInfo(&exception);
641
+ pp = *color;
642
+ #if defined(IMAGEMAGICK_7)
643
+ pp.depth = MAGICKCORE_QUANTUM_DEPTH;
644
+ pp.colorspace = image->colorspace;
645
+ #endif
646
+
647
+ QueryColorname(image, &pp, X11Compliance, name, exception);
648
+ CHECK_EXCEPTION();
649
+ DestroyExceptionInfo(exception);
637
650
 
638
651
  return rb_str_new2(name);
639
652
  }
@@ -647,36 +660,80 @@ rm_pixelpacket_to_color_name(Image *image, PixelPacket *color)
647
660
  * Notes:
648
661
  * - Simply create an Image from the Info, call QueryColorname, and then
649
662
  * destroy the Image.
650
- * - If the Info structure is NULL, creates a new one.
651
663
  * - The default depth is always used, and the matte value is set to False,
652
664
  * which means "don't use the alpha channel".
653
665
  *
654
666
  * @param info the info
655
- * @param color the color intensity as a PixelPacket
667
+ * @param color the color intensity as a PixelColor
656
668
  * @return the named color as a String
657
- * @see rm_pixelpacket_to_color_name
669
+ * @see rm_pixelcolor_to_color_name
658
670
  */
659
671
  VALUE
660
- rm_pixelpacket_to_color_name_info(Info *info, PixelPacket *color)
672
+ rm_pixelcolor_to_color_name_info(Info *info, PixelColor *color)
661
673
  {
662
674
  Image *image;
663
- Info *my_info;
664
- volatile VALUE color_name;
665
-
666
- my_info = info ? info : CloneImageInfo(NULL);
675
+ VALUE color_name;
667
676
 
668
- image = AcquireImage(info);
669
- image->matte = MagickFalse;
670
- color_name = rm_pixelpacket_to_color_name(image, color);
671
- (void) DestroyImage(image);
672
- if (!info)
677
+ image = rm_acquire_image(info);
678
+ if (!image)
673
679
  {
674
- (void) DestroyImageInfo(my_info);
680
+ rb_raise(rb_eNoMemError, "not enough memory to continue.");
675
681
  }
676
682
 
683
+ #if defined(IMAGEMAGICK_7)
684
+ image->alpha_trait = UndefinedPixelTrait;
685
+ #else
686
+ image->matte = MagickFalse;
687
+ #endif
688
+
689
+ color_name = rm_pixelcolor_to_color_name(image, color);
690
+ DestroyImage(image);
691
+
677
692
  return color_name;
678
693
  }
679
694
 
695
+ /**
696
+ * Initializes the MagickPixel structure.
697
+ *
698
+ * No Ruby usage (internal function)
699
+ *
700
+ * @param image the image
701
+ * @param pp the MagickPixel
702
+ */
703
+ void
704
+ rm_init_magickpixel(const Image *image, MagickPixel *pp)
705
+ {
706
+ #if defined(IMAGEMAGICK_7)
707
+ GetPixelInfo(image, pp);
708
+ #else
709
+ GetMagickPixelPacket(image, pp);
710
+ #endif
711
+ }
712
+
713
+ /**
714
+ * Initializes the MagickPixel structure to the specified color.
715
+ *
716
+ * No Ruby usage (internal function)
717
+ *
718
+ * @param pp the MagickPixel
719
+ * @param color the color
720
+ */
721
+ void
722
+ rm_set_magickpixel(MagickPixel *pp, const char *color)
723
+ {
724
+ ExceptionInfo *exception;
725
+
726
+ exception = AcquireExceptionInfo();
727
+
728
+ #if defined(IMAGEMAGICK_7)
729
+ QueryColorCompliance(color, AllCompliance, pp, exception);
730
+ #else
731
+ QueryMagickColor(color, pp, exception);
732
+ #endif
733
+ // This exception is ignored because the color comes from places where we control
734
+ // the value and it is very unlikely that an exception will be thrown.
735
+ DestroyExceptionInfo(exception);
736
+ }
680
737
 
681
738
  /**
682
739
  * Write a temporary copy of the image to the IM registry.
@@ -689,20 +746,21 @@ rm_pixelpacket_to_color_name_info(Info *info, PixelPacket *color)
689
746
  *
690
747
  * @param image the image
691
748
  * @param temp_name the temporary name to use
749
+ * @param temp_name_l the length of temp_name
692
750
  * @return the "filename" of the registered image
693
751
  */
694
752
  void
695
- rm_write_temp_image(Image *image, char *temp_name)
753
+ rm_write_temp_image(Image *image, char *temp_name, size_t temp_name_l)
696
754
  {
697
755
 
698
756
  #define TMPNAM_CLASS_VAR "@@_tmpnam_"
699
757
 
700
758
  MagickBooleanType okay;
701
- ExceptionInfo exception;
702
- volatile VALUE id_value;
759
+ ExceptionInfo *exception;
760
+ VALUE id_value;
703
761
  int id;
704
762
 
705
- GetExceptionInfo(&exception);
763
+ exception = AcquireExceptionInfo();
706
764
 
707
765
 
708
766
  // 'id' is always the value of its previous use
@@ -719,17 +777,18 @@ rm_write_temp_image(Image *image, char *temp_name)
719
777
 
720
778
  id += 1;
721
779
  rb_cv_set(Module_Magick, TMPNAM_CLASS_VAR, INT2FIX(id));
722
- sprintf(temp_name, "mpri:%d", id);
780
+ snprintf(temp_name, temp_name_l, "mpri:%d", id);
723
781
 
724
782
  // Omit "mpri:" from filename to form the key
725
- okay = SetImageRegistry(ImageRegistryType, temp_name+5, image, &exception);
726
- CHECK_EXCEPTION()
727
- DestroyExceptionInfo(&exception);
783
+ okay = SetImageRegistry(ImageRegistryType, temp_name+5, image, exception);
784
+ CHECK_EXCEPTION();
785
+ DestroyExceptionInfo(exception);
728
786
  if (!okay)
729
787
  {
730
788
  rb_raise(rb_eRuntimeError, "SetImageRegistry failed.");
731
789
  }
732
790
 
791
+ RB_GC_GUARD(id_value);
733
792
  }
734
793
 
735
794
 
@@ -768,7 +827,7 @@ rm_not_implemented(void)
768
827
  {
769
828
 
770
829
  rb_raise(rb_eNotImpError, "the `%s' method is not supported by ImageMagick "
771
- MagickLibVersionText, rb_id2name(THIS_FUNC()));
830
+ MagickLibVersionText, rb_id2name(rb_frame_this_func()));
772
831
  }
773
832
 
774
833
 
@@ -782,45 +841,39 @@ rm_not_implemented(void)
782
841
  * the ImageMagickError object in both 1.6.8 and 1.8.0.
783
842
  *
784
843
  * @param msg the error mesage
785
- * @param loc the location of the error
786
844
  * @throw ImageMagickError
787
845
  * @see www.ruby_talk.org/36408.
788
846
  */
789
847
  void
790
- rm_magick_error(const char *msg, const char *loc)
848
+ rm_magick_error(const char *msg)
791
849
  {
792
- volatile VALUE exc, mesg, extra;
850
+ VALUE exc, mesg;
793
851
 
794
852
  mesg = rb_str_new2(msg);
795
- extra = loc ? rb_str_new2(loc) : Qnil;
796
853
 
797
- exc = rb_funcall(Class_ImageMagickError, rm_ID_new, 2, mesg, extra);
798
- (void) rb_funcall(rb_cObject, rb_intern("raise"), 1, exc);
854
+ exc = rb_funcall(Class_ImageMagickError, rm_ID_new, 2, mesg, Qnil);
855
+ rb_funcall(rb_cObject, rb_intern("raise"), 1, exc);
856
+
857
+ RB_GC_GUARD(exc);
858
+ RB_GC_GUARD(mesg);
799
859
  }
800
860
 
801
861
 
802
862
  /**
803
863
  * Initialize a new ImageMagickError object - store the "loc" string in the
804
- * \@magick_location instance variable.
805
- *
806
- * Ruby usage:
807
- * - @verbatim ImageMagickError#initialize(msg) @endverbatim
808
- * - @verbatim ImageMagickError#initialize(msg, loc) @endverbatim
864
+ * magick_location instance variable.
809
865
  *
810
- * Notes:
811
- * - Default loc is nil
812
- *
813
- * @param argc number of input arguments
814
- * @param argv array of input arguments
815
- * @param self this object
816
- * @return self
866
+ * @overload initialize(msg, loc = nil)
867
+ * @param msg [String] the exception message
868
+ * @param loc [String] the location stored in the magick_location instance variable
869
+ * @return [Magick::ImageMagickError] self
817
870
  */
818
871
  VALUE
819
872
  ImageMagickError_initialize(int argc, VALUE *argv, VALUE self)
820
873
  {
821
874
  VALUE super_argv[1] = {(VALUE)0};
822
875
  int super_argc = 0;
823
- volatile VALUE extra = Qnil;
876
+ VALUE extra = Qnil;
824
877
 
825
878
  switch(argc)
826
879
  {
@@ -835,9 +888,10 @@ ImageMagickError_initialize(int argc, VALUE *argv, VALUE self)
835
888
  rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 to 2)", argc);
836
889
  }
837
890
 
838
- (void) rb_call_super(super_argc, (const VALUE *)super_argv);
839
- (void) rb_iv_set(self, "@"MAGICK_LOC, extra);
891
+ rb_call_super(super_argc, (const VALUE *)super_argv);
892
+ rb_iv_set(self, "@"MAGICK_LOC, extra);
840
893
 
894
+ RB_GC_GUARD(extra);
841
895
 
842
896
  return self;
843
897
  }
@@ -855,7 +909,18 @@ ImageMagickError_initialize(int argc, VALUE *argv, VALUE self)
855
909
  const char *
856
910
  rm_get_property(const Image *img, const char *property)
857
911
  {
912
+ #if defined(IMAGEMAGICK_7)
913
+ const char *result;
914
+ ExceptionInfo *exception;
915
+
916
+ exception = AcquireExceptionInfo();
917
+ result = GetImageProperty(img, property, exception);
918
+ CHECK_EXCEPTION();
919
+ DestroyExceptionInfo(exception);
920
+ return result;
921
+ #else
858
922
  return GetImageProperty(img, property);
923
+ #endif
859
924
  }
860
925
 
861
926
 
@@ -865,14 +930,25 @@ rm_get_property(const Image *img, const char *property)
865
930
  * No Ruby usage (internal function)
866
931
  *
867
932
  * @param image the image
868
- * @param property the property name
933
+ * @param property the property name
869
934
  * @param value the property value
870
935
  * @return true if successful, otherwise false
871
936
  */
872
937
  MagickBooleanType
873
938
  rm_set_property(Image *image, const char *property, const char *value)
874
939
  {
940
+ #if defined(IMAGEMAGICK_7)
941
+ ExceptionInfo *exception;
942
+ MagickBooleanType okay;
943
+
944
+ exception = AcquireExceptionInfo();
945
+ okay = SetImageProperty(image, property, value, exception);
946
+ CHECK_EXCEPTION();
947
+ DestroyExceptionInfo(exception);
948
+ return okay;
949
+ #else
875
950
  return SetImageProperty(image, property, value);
951
+ #endif
876
952
  }
877
953
 
878
954
 
@@ -887,24 +963,20 @@ rm_set_property(Image *image, const char *property, const char *value)
887
963
  */
888
964
  void rm_set_user_artifact(Image *images, Info *info)
889
965
  {
890
- #if defined(HAVE_SETIMAGEARTIFACT)
891
- Image *image;
892
966
  const char *value;
893
967
 
894
968
  value = GetImageOption(info, "user");
895
969
  if (value)
896
970
  {
971
+ Image *image;
972
+
897
973
  image = GetFirstImageInList(images);
898
974
  while (image)
899
975
  {
900
- (void) SetImageArtifact(image, "user", value);
976
+ SetImageArtifact(image, "user", value);
901
977
  image = GetNextImageInList(image);
902
978
  }
903
979
  }
904
- #else
905
- images = images;
906
- info = info;
907
- #endif
908
980
  }
909
981
 
910
982
 
@@ -922,25 +994,35 @@ void rm_set_user_artifact(Image *images, Info *info)
922
994
  void
923
995
  rm_get_optional_arguments(VALUE img)
924
996
  {
925
- volatile VALUE OptionalMethodArguments;
926
- volatile VALUE opt_args;
927
- VALUE argv[1];
928
-
929
- // opt_args = Magick::OptionalMethodArguments.new(img)
930
- // opt_args.instance_eval { block }
931
- if (rb_block_given_p())
932
- {
933
- OptionalMethodArguments = rb_const_get_from(Module_Magick, rb_intern("OptionalMethodArguments"));
934
- argv[0] = img;
935
- opt_args = rb_class_new_instance(1, argv, OptionalMethodArguments);
936
- (void) rb_obj_instance_eval(0, NULL, opt_args);
937
- }
938
-
939
- return;
997
+ VALUE optional_method_arguments;
998
+ VALUE opt_args;
999
+ VALUE argv[1];
1000
+
1001
+ // opt_args = Magick::OptionalMethodArguments.new(img)
1002
+ // opt_args.instance_eval { block }
1003
+ if (rb_block_given_p())
1004
+ {
1005
+ optional_method_arguments = rb_const_get_from(Module_Magick, rb_intern("OptionalMethodArguments"));
1006
+ argv[0] = img;
1007
+ opt_args = rb_class_new_instance(1, argv, optional_method_arguments);
1008
+
1009
+ if (rb_proc_arity(rb_block_proc()) == 0)
1010
+ {
1011
+ rb_obj_instance_eval(0, NULL, opt_args);
1012
+ }
1013
+ else
1014
+ {
1015
+ rb_yield(opt_args);
1016
+ }
1017
+ }
1018
+
1019
+ RB_GC_GUARD(optional_method_arguments);
1020
+ RB_GC_GUARD(opt_args);
1021
+
1022
+ return;
940
1023
  }
941
1024
 
942
1025
 
943
- #if defined(HAVE_SETIMAGEARTIFACT)
944
1026
  /**
945
1027
  * Copy image options from the Info structure to the Image structure.
946
1028
  *
@@ -952,21 +1034,21 @@ rm_get_optional_arguments(VALUE img)
952
1034
  static void copy_options(Image *image, Info *info)
953
1035
  {
954
1036
  char property[MaxTextExtent];
955
- const char *value, *option;
1037
+ const char *option;
956
1038
 
957
1039
  ResetImageOptionIterator(info);
958
1040
  for (option = GetNextImageOption(info); option; option = GetNextImageOption(info))
959
1041
  {
960
- value = GetImageOption(info,option);
1042
+ const char *value;
1043
+
1044
+ value = GetImageOption(info, option);
961
1045
  if (value)
962
1046
  {
963
- strncpy(property, value, MaxTextExtent);
964
- property[MaxTextExtent-1] = '\0';
965
- (void) SetImageArtifact(image, property, value);
1047
+ strlcpy(property, value, sizeof(property));
1048
+ SetImageArtifact(image, property, value);
966
1049
  }
967
1050
  }
968
1051
  }
969
- #endif
970
1052
 
971
1053
 
972
1054
  /**
@@ -983,16 +1065,19 @@ void rm_sync_image_options(Image *image, Info *info)
983
1065
  MagickStatusType flags;
984
1066
  GeometryInfo geometry_info;
985
1067
  const char *option;
1068
+ #if defined(IMAGEMAGICK_7)
1069
+ ExceptionInfo *exception;
1070
+ #endif
986
1071
 
987
1072
  // The option strings will be set only when their attribute values were
988
1073
  // set in the optional argument block.
989
- option = GetImageOption(info,"background");
1074
+ option = GetImageOption(info, "background");
990
1075
  if (option)
991
1076
  {
992
1077
  image->background_color = info->background_color;
993
1078
  }
994
1079
 
995
- option = GetImageOption(info,"bordercolor");
1080
+ option = GetImageOption(info, "bordercolor");
996
1081
  if (option)
997
1082
  {
998
1083
  image->border_color = info->border_color;
@@ -1000,7 +1085,16 @@ void rm_sync_image_options(Image *image, Info *info)
1000
1085
 
1001
1086
  if (info->colorspace != UndefinedColorspace)
1002
1087
  {
1003
- image->colorspace = info->colorspace;
1088
+ #if defined(IMAGEMAGICK_7)
1089
+ exception = AcquireExceptionInfo();
1090
+ SetImageColorspace(image, info->colorspace, exception);
1091
+ // We should not throw an exception in this method because we will
1092
+ // leak memory in the place where this method is called. And that is
1093
+ // why the exception is being ignored here.
1094
+ DestroyExceptionInfo(exception);
1095
+ #else
1096
+ SetImageColorspace(image, info->colorspace);
1097
+ #endif
1004
1098
  }
1005
1099
 
1006
1100
  if (info->compression != UndefinedCompression)
@@ -1017,11 +1111,20 @@ void rm_sync_image_options(Image *image, Info *info)
1017
1111
  if (info->density)
1018
1112
  {
1019
1113
  flags = ParseGeometry(info->density, &geometry_info);
1114
+ #if defined(IMAGEMAGICK_7)
1115
+ image->resolution.x = geometry_info.rho;
1116
+ image->resolution.y = geometry_info.sigma;
1117
+ #else
1020
1118
  image->x_resolution = geometry_info.rho;
1021
1119
  image->y_resolution = geometry_info.sigma;
1120
+ #endif
1022
1121
  if ((flags & SigmaValue) == 0)
1023
1122
  {
1123
+ #if defined(IMAGEMAGICK_7)
1124
+ image->resolution.y = image->resolution.x;
1125
+ #else
1024
1126
  image->y_resolution = image->x_resolution;
1127
+ #endif
1025
1128
  }
1026
1129
  }
1027
1130
 
@@ -1057,7 +1160,7 @@ void rm_sync_image_options(Image *image, Info *info)
1057
1160
  image->interlace = info->interlace;
1058
1161
  }
1059
1162
 
1060
- option = GetImageOption(info,"mattecolor");
1163
+ option = GetImageOption(info, "mattecolor");
1061
1164
  if (option)
1062
1165
  {
1063
1166
  image->matte_color = info->matte_color;
@@ -1070,7 +1173,7 @@ void rm_sync_image_options(Image *image, Info *info)
1070
1173
 
1071
1174
  if (info->page)
1072
1175
  {
1073
- (void)ParseAbsoluteGeometry(info->page, &image->page);
1176
+ ParseAbsoluteGeometry(info->page, &image->page);
1074
1177
  }
1075
1178
 
1076
1179
  if (info->quality != 0UL)
@@ -1087,7 +1190,7 @@ void rm_sync_image_options(Image *image, Info *info)
1087
1190
  option = GetImageOption(info, "tile-offset");
1088
1191
  if (option)
1089
1192
  {
1090
- (void)ParseAbsoluteGeometry(option, &image->tile_offset);
1193
+ ParseAbsoluteGeometry(option, &image->tile_offset);
1091
1194
  }
1092
1195
 
1093
1196
  option = GetImageOption(info, "transparent");
@@ -1096,12 +1199,10 @@ void rm_sync_image_options(Image *image, Info *info)
1096
1199
  image->transparent_color = info->transparent_color;
1097
1200
  }
1098
1201
 
1099
- #if defined(HAVE_ST_TYPE)
1100
1202
  if (info->type != UndefinedType)
1101
1203
  {
1102
1204
  image->type = info->type;
1103
1205
  }
1104
- #endif
1105
1206
 
1106
1207
  if (info->units != UndefinedResolution)
1107
1208
  {
@@ -1113,8 +1214,13 @@ void rm_sync_image_options(Image *image, Info *info)
1113
1214
  {
1114
1215
  if (info->units == PixelsPerCentimeterResolution)
1115
1216
  {
1217
+ #if defined(IMAGEMAGICK_7)
1218
+ image->resolution.x /= 2.54;
1219
+ image->resolution.y /= 2.54;
1220
+ #else
1116
1221
  image->x_resolution /= 2.54;
1117
1222
  image->y_resolution /= 2.54;
1223
+ #endif
1118
1224
  }
1119
1225
  break;
1120
1226
  }
@@ -1122,8 +1228,13 @@ void rm_sync_image_options(Image *image, Info *info)
1122
1228
  {
1123
1229
  if (info->units == PixelsPerInchResolution)
1124
1230
  {
1231
+ #if defined(IMAGEMAGICK_7)
1232
+ image->resolution.x *= 2.54;
1233
+ image->resolution.y *= 2.54;
1234
+ #else
1125
1235
  image->x_resolution *= 2.54;
1126
1236
  image->y_resolution *= 2.54;
1237
+ #endif
1127
1238
  }
1128
1239
  break;
1129
1240
  }
@@ -1135,9 +1246,7 @@ void rm_sync_image_options(Image *image, Info *info)
1135
1246
  image->units = info->units;
1136
1247
  }
1137
1248
 
1138
- #if defined(HAVE_SETIMAGEARTIFACT)
1139
1249
  copy_options(image, info);
1140
- #endif
1141
1250
  }
1142
1251
 
1143
1252
 
@@ -1159,9 +1268,17 @@ rm_exif_by_entry(Image *image)
1159
1268
  const char *property, *value;
1160
1269
  char *str;
1161
1270
  size_t len = 0, property_l, value_l;
1162
- volatile VALUE v;
1271
+ VALUE v;
1272
+ #if defined(IMAGEMAGICK_7)
1273
+ ExceptionInfo *exception;
1274
+
1275
+ exception = AcquireExceptionInfo();
1276
+ GetImageProperty(image, "exif:*", exception);
1277
+ CHECK_EXCEPTION();
1278
+ #else
1279
+ GetImageProperty(image, "exif:*");
1280
+ #endif
1163
1281
 
1164
- (void) GetImageProperty(image, "exif:*");
1165
1282
  ResetImagePropertyIterator(image);
1166
1283
  property = GetNextImageProperty(image);
1167
1284
 
@@ -1169,7 +1286,7 @@ rm_exif_by_entry(Image *image)
1169
1286
  while (property)
1170
1287
  {
1171
1288
  // ignore properties that don't start with "exif:"
1172
- property_l = strlen(property);
1289
+ property_l = rm_strnlen_s(property, MaxTextExtent);
1173
1290
  if (property_l > 5 && rm_strncasecmp(property, "exif:", 5) == 0)
1174
1291
  {
1175
1292
  if (len > 0)
@@ -1177,11 +1294,16 @@ rm_exif_by_entry(Image *image)
1177
1294
  len += 1; // there will be a \n between property=value entries
1178
1295
  }
1179
1296
  len += property_l - 5;
1180
- value = GetImageProperty(image,property);
1297
+ #if defined(IMAGEMAGICK_7)
1298
+ value = GetImageProperty(image, property, exception);
1299
+ CHECK_EXCEPTION();
1300
+ #else
1301
+ value = GetImageProperty(image, property);
1302
+ #endif
1181
1303
  if (value)
1182
1304
  {
1183
1305
  // add 1 for the = between property and value
1184
- len += 1 + strlen(value);
1306
+ len += 1 + rm_strnlen_s(value, MaxTextExtent);
1185
1307
  }
1186
1308
  }
1187
1309
  property = GetNextImageProperty(image);
@@ -1189,8 +1311,12 @@ rm_exif_by_entry(Image *image)
1189
1311
 
1190
1312
  if (len == 0)
1191
1313
  {
1314
+ #if defined(IMAGEMAGICK_7)
1315
+ DestroyExceptionInfo(exception);
1316
+ #endif
1192
1317
  return Qnil;
1193
1318
  }
1319
+
1194
1320
  str = xmalloc(len);
1195
1321
  len = 0;
1196
1322
 
@@ -1200,7 +1326,7 @@ rm_exif_by_entry(Image *image)
1200
1326
 
1201
1327
  while (property)
1202
1328
  {
1203
- property_l = strlen(property);
1329
+ property_l = rm_strnlen_s(property, MaxTextExtent);
1204
1330
  if (property_l > 5 && rm_strncasecmp(property, "exif:", 5) == 0)
1205
1331
  {
1206
1332
  if (len > 0)
@@ -1209,10 +1335,19 @@ rm_exif_by_entry(Image *image)
1209
1335
  }
1210
1336
  memcpy(str+len, property+5, property_l-5);
1211
1337
  len += property_l - 5;
1212
- value = GetImageProperty(image,property);
1338
+ #if defined(IMAGEMAGICK_7)
1339
+ value = GetImageProperty(image, property, exception);
1340
+ if (rm_should_raise_exception(exception, RetainExceptionRetention))
1341
+ {
1342
+ xfree(str);
1343
+ rm_raise_exception(exception);
1344
+ }
1345
+ #else
1346
+ value = GetImageProperty(image, property);
1347
+ #endif
1213
1348
  if (value)
1214
1349
  {
1215
- value_l = strlen(value);
1350
+ value_l = rm_strnlen_s(value, MaxTextExtent);
1216
1351
  str[len++] = '=';
1217
1352
  memcpy(str+len, value, value_l);
1218
1353
  len += value_l;
@@ -1221,8 +1356,15 @@ rm_exif_by_entry(Image *image)
1221
1356
  property = GetNextImageProperty(image);
1222
1357
  }
1223
1358
 
1359
+ #if defined(IMAGEMAGICK_7)
1360
+ DestroyExceptionInfo(exception);
1361
+ #endif
1362
+
1224
1363
  v = rb_str_new(str, len);
1225
1364
  xfree(str);
1365
+
1366
+ RB_GC_GUARD(v);
1367
+
1226
1368
  return v;
1227
1369
  }
1228
1370
 
@@ -1245,9 +1387,16 @@ rm_exif_by_number(Image *image)
1245
1387
  const char *property, *value;
1246
1388
  char *str;
1247
1389
  size_t len = 0, property_l, value_l;
1248
- volatile VALUE v;
1390
+ VALUE v;
1391
+ #if defined(IMAGEMAGICK_7)
1392
+ ExceptionInfo *exception;
1249
1393
 
1250
- (void) GetImageProperty(image, "exif:!");
1394
+ exception = AcquireExceptionInfo();
1395
+ GetImageProperty(image, "exif:!", exception);
1396
+ CHECK_EXCEPTION();
1397
+ #else
1398
+ GetImageProperty(image, "exif:!");
1399
+ #endif
1251
1400
  ResetImagePropertyIterator(image);
1252
1401
  property = GetNextImageProperty(image);
1253
1402
 
@@ -1255,7 +1404,7 @@ rm_exif_by_number(Image *image)
1255
1404
  while (property)
1256
1405
  {
1257
1406
  // ignore properties that don't start with "#"
1258
- property_l = strlen(property);
1407
+ property_l = rm_strnlen_s(property, MaxTextExtent);
1259
1408
  if (property_l > 1 && property[0] == '#')
1260
1409
  {
1261
1410
  if (len > 0)
@@ -1263,11 +1412,16 @@ rm_exif_by_number(Image *image)
1263
1412
  len += 1; // there will be a \n between property=value entries
1264
1413
  }
1265
1414
  len += property_l;
1266
- value = GetImageProperty(image,property);
1415
+ #if defined(IMAGEMAGICK_7)
1416
+ value = GetImageProperty(image, property, exception);
1417
+ CHECK_EXCEPTION();
1418
+ #else
1419
+ value = GetImageProperty(image, property);
1420
+ #endif
1267
1421
  if (value)
1268
1422
  {
1269
1423
  // add 1 for the = between property and value
1270
- len += 1 + strlen(value);
1424
+ len += 1 + rm_strnlen_s(value, MaxTextExtent);
1271
1425
  }
1272
1426
  }
1273
1427
  property = GetNextImageProperty(image);
@@ -1275,8 +1429,12 @@ rm_exif_by_number(Image *image)
1275
1429
 
1276
1430
  if (len == 0)
1277
1431
  {
1432
+ #if defined(IMAGEMAGICK_7)
1433
+ DestroyExceptionInfo(exception);
1434
+ #endif
1278
1435
  return Qnil;
1279
1436
  }
1437
+
1280
1438
  str = xmalloc(len);
1281
1439
  len = 0;
1282
1440
 
@@ -1286,7 +1444,7 @@ rm_exif_by_number(Image *image)
1286
1444
 
1287
1445
  while (property)
1288
1446
  {
1289
- property_l = strlen(property);
1447
+ property_l = rm_strnlen_s(property, MaxTextExtent);
1290
1448
  if (property_l > 1 && property[0] == '#')
1291
1449
  {
1292
1450
  if (len > 0)
@@ -1295,10 +1453,19 @@ rm_exif_by_number(Image *image)
1295
1453
  }
1296
1454
  memcpy(str+len, property, property_l);
1297
1455
  len += property_l;
1298
- value = GetImageProperty(image,property);
1456
+ #if defined(IMAGEMAGICK_7)
1457
+ value = GetImageProperty(image, property, exception);
1458
+ if (rm_should_raise_exception(exception, RetainExceptionRetention))
1459
+ {
1460
+ xfree(str);
1461
+ rm_raise_exception(exception);
1462
+ }
1463
+ #else
1464
+ value = GetImageProperty(image, property);
1465
+ #endif
1299
1466
  if (value)
1300
1467
  {
1301
- value_l = strlen(value);
1468
+ value_l = rm_strnlen_s(value, MaxTextExtent);
1302
1469
  str[len++] = '=';
1303
1470
  memcpy(str+len, value, value_l);
1304
1471
  len += value_l;
@@ -1307,69 +1474,16 @@ rm_exif_by_number(Image *image)
1307
1474
  property = GetNextImageProperty(image);
1308
1475
  }
1309
1476
 
1477
+ #if defined(IMAGEMAGICK_7)
1478
+ DestroyExceptionInfo(exception);
1479
+ #endif
1480
+
1310
1481
  v = rb_str_new(str, len);
1311
1482
  xfree(str);
1312
- return v;
1313
- }
1314
-
1315
1483
 
1316
- /**
1317
- * Get the values from a Geometry object and return them in C variables.
1318
- *
1319
- * No Ruby usage (internal function)
1320
- *
1321
- * Notes:
1322
- * - No return value: modifies x, y, width, height, and flag
1323
- *
1324
- * @param geom the Geometry object
1325
- * @param x pointer to the x position of the start of the rectangle
1326
- * @param y pointer to the y position of the start of the rectangle
1327
- * @param width pointer to the width of the rectangle
1328
- * @param height pointer to the height of the rectangle
1329
- * @param flag pointer to the Geometry's flag
1330
- */
1331
- void
1332
- rm_get_geometry(
1333
- VALUE geom,
1334
- long *x,
1335
- long *y,
1336
- unsigned long *width,
1337
- unsigned long *height,
1338
- int *flag)
1339
- {
1340
- VALUE v;
1341
-
1342
- v = rb_funcall(geom, rm_ID_x, 0);
1343
- *x = NUM2LONG(v);
1344
- v = rb_funcall(geom, rm_ID_y, 0);
1345
- *y = NUM2LONG(v);
1346
- v = rb_funcall(geom, rm_ID_width, 0);
1347
- *width = NUM2ULONG(v);
1348
- v = rb_funcall(geom, rm_ID_height, 0);
1349
- *height = NUM2ULONG(v);
1350
-
1351
- // Getting the flag field is a bit more difficult since it's
1352
- // supposed to be an instance of the GeometryValue Enum class. We
1353
- // may not know the VALUE for the GeometryValue class, and we
1354
- // need to check that the flag field is an instance of that class.
1355
- if (flag)
1356
- {
1357
- MagickEnum *magick_enum;
1358
-
1359
- v = rb_funcall(geom, rm_ID_flag, 0);
1360
- if (!Class_GeometryValue)
1361
- {
1362
- Class_GeometryValue = rb_const_get(Module_Magick, rm_ID_GeometryValue);
1363
- }
1364
- if (CLASS_OF(v) != Class_GeometryValue)
1365
- {
1366
- rb_raise(rb_eTypeError, "wrong enumeration type - expected %s, got %s"
1367
- , rb_class2name(Class_GeometryValue),rb_class2name(CLASS_OF(v)));
1368
- }
1369
- Data_Get_Struct(v, MagickEnum, magick_enum);
1370
- *flag = magick_enum->val;
1371
- }
1484
+ RB_GC_GUARD(v);
1372
1485
 
1486
+ return v;
1373
1487
  }
1374
1488
 
1375
1489
 
@@ -1389,16 +1503,16 @@ Image *
1389
1503
  rm_clone_image(Image *image)
1390
1504
  {
1391
1505
  Image *clone;
1392
- ExceptionInfo exception;
1506
+ ExceptionInfo *exception;
1393
1507
 
1394
- GetExceptionInfo(&exception);
1395
- clone = CloneImage(image, 0, 0, MagickTrue, &exception);
1508
+ exception = AcquireExceptionInfo();
1509
+ clone = CloneImage(image, 0, 0, MagickTrue, exception);
1396
1510
  if (!clone)
1397
1511
  {
1398
1512
  rb_raise(rb_eNoMemError, "not enough memory to continue");
1399
1513
  }
1400
- rm_check_exception(&exception, clone, DestroyOnError);
1401
- (void) DestroyExceptionInfo(&exception);
1514
+ rm_check_exception(exception, clone, DestroyOnError);
1515
+ DestroyExceptionInfo(exception);
1402
1516
 
1403
1517
  return clone;
1404
1518
  }
@@ -1421,15 +1535,25 @@ rm_clone_image(Image *image)
1421
1535
  */
1422
1536
  MagickBooleanType
1423
1537
  rm_progress_monitor(
1424
- const char *tag,
1538
+ const char *tag ATTRIBUTE_UNUSED,
1425
1539
  const MagickOffsetType of,
1426
1540
  const MagickSizeType sp,
1427
1541
  void *client_data)
1428
1542
  {
1429
- volatile VALUE rval;
1430
- volatile VALUE method, offset, span;
1543
+ VALUE rval;
1544
+ VALUE method, offset, span;
1431
1545
 
1432
- tag = tag; // defeat gcc message
1546
+ // Check running thread.
1547
+ if (rm_current_thread_id() != rm_main_thread_id)
1548
+ {
1549
+ // ImageMagick might call back in a different thread than Ruby is running in.
1550
+ // If it is a different thread, it would not have a Ruby GVL and
1551
+ // it could not retrieve properly Ruby stack.
1552
+
1553
+ // Unfortunately, there is no API available to check if the current thread has a GVL,
1554
+ // so the thread id was checked in here.
1555
+ return MagickTrue;
1556
+ }
1433
1557
 
1434
1558
  #if defined(HAVE_LONG_LONG) // defined in Ruby's defines.h
1435
1559
  offset = rb_ll2inum(of);
@@ -1439,10 +1563,15 @@ rm_progress_monitor(
1439
1563
  span = rb_uint2big((unsigned long)sp);
1440
1564
  #endif
1441
1565
 
1442
- method = rb_str_new2(rb_id2name(THIS_FUNC()));
1566
+ method = rb_id2str(rb_frame_this_func());
1443
1567
 
1444
1568
  rval = rb_funcall((VALUE)client_data, rm_ID_call, 3, method, offset, span);
1445
1569
 
1570
+ RB_GC_GUARD(rval);
1571
+ RB_GC_GUARD(method);
1572
+ RB_GC_GUARD(offset);
1573
+ RB_GC_GUARD(span);
1574
+
1446
1575
  return RTEST(rval) ? MagickTrue : MagickFalse;
1447
1576
  }
1448
1577
 
@@ -1467,11 +1596,12 @@ rm_split(Image *image)
1467
1596
  }
1468
1597
  while (image)
1469
1598
  {
1470
- (void) RemoveFirstImageFromList(&image);
1599
+ RemoveFirstImageFromList(&image);
1471
1600
  }
1472
1601
  }
1473
1602
 
1474
1603
 
1604
+ #if defined(IMAGEMAGICK_6)
1475
1605
  /**
1476
1606
  * If an ExceptionInfo struct in a list of images indicates a warning, issue a
1477
1607
  * warning message. If an ExceptionInfo struct indicates an error, raise an
@@ -1486,7 +1616,7 @@ rm_split(Image *image)
1486
1616
  void
1487
1617
  rm_check_image_exception(Image *imglist, ErrorRetention retention)
1488
1618
  {
1489
- ExceptionInfo exception;
1619
+ ExceptionInfo *exception;
1490
1620
  Image *badboy = NULL;
1491
1621
  Image *image;
1492
1622
 
@@ -1495,7 +1625,7 @@ rm_check_image_exception(Image *imglist, ErrorRetention retention)
1495
1625
  return;
1496
1626
  }
1497
1627
 
1498
- GetExceptionInfo(&exception);
1628
+ exception = AcquireExceptionInfo();
1499
1629
 
1500
1630
  // Find the image with the highest severity
1501
1631
  image = GetFirstImageInList(imglist);
@@ -1506,7 +1636,7 @@ rm_check_image_exception(Image *imglist, ErrorRetention retention)
1506
1636
  if (!badboy || image->exception.severity > badboy->exception.severity)
1507
1637
  {
1508
1638
  badboy = image;
1509
- InheritException(&exception, &badboy->exception);
1639
+ InheritException(exception, &badboy->exception);
1510
1640
  }
1511
1641
 
1512
1642
  ClearMagickException(&image->exception);
@@ -1516,10 +1646,37 @@ rm_check_image_exception(Image *imglist, ErrorRetention retention)
1516
1646
 
1517
1647
  if (badboy)
1518
1648
  {
1519
- rm_check_exception(&exception, imglist, retention);
1649
+ rm_check_exception(exception, imglist, retention);
1520
1650
  }
1521
1651
 
1522
- (void) DestroyExceptionInfo(&exception);
1652
+ DestroyExceptionInfo(exception);
1653
+ }
1654
+ #endif
1655
+
1656
+
1657
+ #define ERROR_MSG_SIZE 1024
1658
+ /**
1659
+ * Formats the exception into the message buffer
1660
+ *
1661
+ * No Ruby usage (internal function)
1662
+ *
1663
+ * @param severity information about the severity of the error
1664
+ * @param reason the reason for the error
1665
+ * @param description description of the error
1666
+ * @param msg the buffer where the exception message should be formated in
1667
+ */
1668
+ static void
1669
+ format_exception(const ExceptionType severity, const char *reason, const char *description, char *msg)
1670
+ {
1671
+ int len;
1672
+ memset(msg, 0, ERROR_MSG_SIZE);
1673
+
1674
+ len = snprintf(msg, ERROR_MSG_SIZE, "%s%s%s",
1675
+ GetLocaleExceptionMessage(severity, reason),
1676
+ description ? ": " : "",
1677
+ description ? GetLocaleExceptionMessage(severity, description) : "");
1678
+
1679
+ msg[len] = '\0';
1523
1680
  }
1524
1681
 
1525
1682
 
@@ -1558,11 +1715,10 @@ rm_check_exception(ExceptionInfo *exception, Image *imglist, ErrorRetention rete
1558
1715
  void
1559
1716
  rm_warning_handler(const ExceptionType severity, const char *reason, const char *description)
1560
1717
  {
1561
- ExceptionType dummy;
1562
-
1563
- rb_warning("RMagick: %s: `%s'", reason, description);
1564
- dummy = severity;
1565
- dummy = dummy;
1718
+ rb_warning("RMagick: %s%s%s",
1719
+ GetLocaleExceptionMessage(severity, reason),
1720
+ description ? ": " : "",
1721
+ description ? GetLocaleExceptionMessage(severity, description) : "");
1566
1722
  }
1567
1723
 
1568
1724
 
@@ -1571,28 +1727,18 @@ rm_warning_handler(const ExceptionType severity, const char *reason, const char
1571
1727
  *
1572
1728
  * No Ruby usage (internal function)
1573
1729
  *
1574
- * @param severity information about the severity of the error (ignored)
1730
+ * @param severity information about the severity of the error
1575
1731
  * @param reason the reason for the error
1576
1732
  * @param description description of the error
1577
1733
  */
1578
1734
  void
1579
1735
  rm_error_handler(const ExceptionType severity, const char *reason, const char *description)
1580
1736
  {
1581
- char msg[500];
1582
- int len;
1583
- ExceptionType dummy;
1737
+ char msg[ERROR_MSG_SIZE];
1584
1738
 
1585
- memset(msg, 0, sizeof(msg));
1586
- #if defined(HAVE_SNPRINTF)
1587
- len = snprintf(msg, sizeof(msg), "%s: `%s'", reason, description);
1588
- #else
1589
- len = sprintf(msg, "%.250s: `%.240s'", reason, description);
1590
- #endif
1591
- msg[len] = '\0';
1739
+ format_exception(severity, reason, description, msg);
1592
1740
 
1593
- rm_magick_error(msg, NULL);
1594
- dummy = severity;
1595
- dummy = dummy;
1741
+ rm_magick_error(msg);
1596
1742
  }
1597
1743
 
1598
1744
 
@@ -1603,14 +1749,16 @@ rm_error_handler(const ExceptionType severity, const char *reason, const char *d
1603
1749
  *
1604
1750
  * @param severity information about the severity of the error
1605
1751
  * @param reason the reason for the error
1606
- * @param description description of the error (ignored)
1752
+ * @param description description of the error
1607
1753
  * @throw FatalImageMagickError
1608
1754
  */
1609
1755
  void
1610
1756
  rm_fatal_error_handler(const ExceptionType severity, const char *reason, const char *description)
1611
1757
  {
1612
- rb_raise(Class_FatalImageMagickError, GetLocaleExceptionMessage(severity, reason));
1613
- description = description;
1758
+ rb_raise(Class_FatalImageMagickError, "%s%s%s",
1759
+ GetLocaleExceptionMessage(severity, reason),
1760
+ description ? ": " : "",
1761
+ description ? GetLocaleExceptionMessage(severity, description) : "");
1614
1762
  }
1615
1763
 
1616
1764
 
@@ -1629,27 +1777,12 @@ rm_fatal_error_handler(const ExceptionType severity, const char *reason, const c
1629
1777
  static void
1630
1778
  handle_exception(ExceptionInfo *exception, Image *imglist, ErrorRetention retention)
1631
1779
  {
1632
-
1633
- char reason[500];
1634
- char desc[500];
1635
- char msg[sizeof(reason)+sizeof(desc)+20];
1636
-
1637
- memset(msg, 0, sizeof(msg));
1638
-
1780
+ char msg[ERROR_MSG_SIZE];
1639
1781
 
1640
1782
  // Handle simple warning
1641
1783
  if (exception->severity < ErrorException)
1642
1784
  {
1643
- #if defined(HAVE_SNPRINTF)
1644
- snprintf(msg, sizeof(msg)-1, "RMagick: %s%s%s",
1645
- #else
1646
- sprintf(msg, "RMagick: %.500s%s%.500s",
1647
- #endif
1648
- GetLocaleExceptionMessage(exception->severity, exception->reason),
1649
- exception->description ? ": " : "",
1650
- exception->description ? GetLocaleExceptionMessage(exception->severity, exception->description) : "");
1651
- msg[sizeof(msg)-1] = '\0';
1652
- rb_warning(msg);
1785
+ rm_warning_handler(exception->severity, exception->reason, exception->description);
1653
1786
 
1654
1787
  // Caller deletes ExceptionInfo...
1655
1788
 
@@ -1665,7 +1798,7 @@ handle_exception(ExceptionInfo *exception, Image *imglist, ErrorRetention retent
1665
1798
  {
1666
1799
  if (retention == DestroyOnError)
1667
1800
  {
1668
- (void) DestroyImageList(imglist);
1801
+ DestroyImageList(imglist);
1669
1802
  imglist = NULL;
1670
1803
  }
1671
1804
  else
@@ -1674,40 +1807,11 @@ handle_exception(ExceptionInfo *exception, Image *imglist, ErrorRetention retent
1674
1807
  }
1675
1808
  }
1676
1809
 
1810
+ format_exception(exception->severity, exception->reason, exception->description, msg);
1677
1811
 
1678
- // Clone the ExceptionInfo with all arguments on the stack.
1679
- memset(reason, 0, sizeof(reason));
1680
- memset(desc, 0, sizeof(desc));
1681
-
1682
- if (exception->reason)
1683
- {
1684
- strncpy(reason, exception->reason, sizeof(reason)-1);
1685
- reason[sizeof(reason)-1] = '\0';
1686
- }
1687
- if (exception->description)
1688
- {
1689
- strncpy(desc, exception->description, sizeof(desc)-1);
1690
- desc[sizeof(desc)-1] = '\0';
1691
- }
1692
-
1693
-
1694
- #if defined(HAVE_SNPRINTF)
1695
- snprintf(msg, sizeof(msg)-1, "%s%s%s",
1696
- GetLocaleExceptionMessage(exception->severity, reason),
1697
- desc[0] ? ": " : "",
1698
- desc[0] ? GetLocaleExceptionMessage(exception->severity, desc) : "");
1699
- #else
1700
- sprintf(msg, "%.*s%s%.*s",
1701
- sizeof(reason)-1, GetLocaleExceptionMessage(exception->severity, reason),
1702
- desc[0] ? ": " : "",
1703
- sizeof(desc)-1, desc[0] ? GetLocaleExceptionMessage(exception->severity, desc) : "");
1704
- #endif
1705
-
1706
- msg[sizeof(msg)-1] = '\0';
1707
-
1708
- (void) DestroyExceptionInfo(exception);
1709
- rm_magick_error(msg, NULL);
1812
+ DestroyExceptionInfo(exception);
1710
1813
 
1814
+ rm_magick_error(msg);
1711
1815
  }
1712
1816
 
1713
1817
 
@@ -1728,3 +1832,69 @@ rm_ensure_result(Image *image)
1728
1832
  }
1729
1833
  }
1730
1834
 
1835
+
1836
+ /**
1837
+ * Checks if an error should be raised for the exception.
1838
+ *
1839
+ * No Ruby usage (internal function)
1840
+ *
1841
+ * @param exception information about the exception
1842
+ * @param retention retention strategy for the exception in case there was no error
1843
+ */
1844
+ MagickBooleanType
1845
+ rm_should_raise_exception(ExceptionInfo *exception, const ExceptionRetention retention)
1846
+ {
1847
+ if (exception->severity < ErrorException)
1848
+ {
1849
+ if (exception->severity != UndefinedException)
1850
+ {
1851
+ rm_warning_handler(exception->severity, exception->reason, exception->description);
1852
+ }
1853
+
1854
+ if (retention == DestroyExceptionRetention)
1855
+ {
1856
+ DestroyExceptionInfo(exception);
1857
+ }
1858
+
1859
+ return MagickFalse;
1860
+ }
1861
+
1862
+ return MagickTrue;
1863
+ }
1864
+
1865
+
1866
+ /**
1867
+ * Raises an exception.
1868
+ *
1869
+ * No Ruby usage (internal function)
1870
+ *
1871
+ * @param exception information about the exception
1872
+ */
1873
+ void
1874
+ rm_raise_exception(ExceptionInfo *exception)
1875
+ {
1876
+ char msg[ERROR_MSG_SIZE];
1877
+
1878
+ format_exception(exception->severity, exception->reason, exception->description, msg);
1879
+
1880
+ DestroyExceptionInfo(exception);
1881
+
1882
+ rm_magick_error(msg);
1883
+ }
1884
+
1885
+ /**
1886
+ * Get current thread id.
1887
+ *
1888
+ * No Ruby usage (internal function)
1889
+ *
1890
+ * @return thread id
1891
+ */
1892
+ unsigned long long
1893
+ rm_current_thread_id()
1894
+ {
1895
+ #if defined(_WIN32)
1896
+ return (unsigned long long)GetCurrentThreadId();
1897
+ #else
1898
+ return (unsigned long long)pthread_self();
1899
+ #endif
1900
+ }