rmagick-windows 2.16.1

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 (393) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +14 -0
  3. data/.gitignore +23 -0
  4. data/.hound.yml +2 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +340 -0
  7. data/.simplecov +27 -0
  8. data/.travis.yml +60 -0
  9. data/CHANGELOG.md +915 -0
  10. data/CODE_OF_CONDUCT.md +13 -0
  11. data/CONTRIBUTING.md +50 -0
  12. data/Doxyfile +1514 -0
  13. data/Gemfile +10 -0
  14. data/LICENSE +20 -0
  15. data/README.textile +257 -0
  16. data/Rakefile +188 -0
  17. data/before_install_linux.sh +32 -0
  18. data/before_install_osx.sh +2 -0
  19. data/deprecated/RMagick.rb +6 -0
  20. data/doc/.cvsignore +1 -0
  21. data/doc/comtasks.html +287 -0
  22. data/doc/constants.html +1581 -0
  23. data/doc/css/doc.css +299 -0
  24. data/doc/css/popup.css +34 -0
  25. data/doc/css/ref.css +67 -0
  26. data/doc/draw.html +3272 -0
  27. data/doc/ex/InitialCoords.rb +22 -0
  28. data/doc/ex/NewCoordSys.rb +30 -0
  29. data/doc/ex/OrigCoordSys.rb +16 -0
  30. data/doc/ex/PreserveAspectRatio.rb +204 -0
  31. data/doc/ex/RotateScale.rb +36 -0
  32. data/doc/ex/Skew.rb +38 -0
  33. data/doc/ex/Use01.rb +15 -0
  34. data/doc/ex/Use02.rb +20 -0
  35. data/doc/ex/Use03.rb +16 -0
  36. data/doc/ex/ViewBox.rb +31 -0
  37. data/doc/ex/adaptive_threshold.rb +9 -0
  38. data/doc/ex/add_noise.rb +16 -0
  39. data/doc/ex/affine.rb +48 -0
  40. data/doc/ex/affine_transform.rb +20 -0
  41. data/doc/ex/arc.rb +49 -0
  42. data/doc/ex/arcpath.rb +32 -0
  43. data/doc/ex/arcs01.rb +28 -0
  44. data/doc/ex/arcs02.rb +59 -0
  45. data/doc/ex/average.rb +15 -0
  46. data/doc/ex/axes.rb +64 -0
  47. data/doc/ex/baseline_shift01.rb +17 -0
  48. data/doc/ex/bilevel_channel.rb +8 -0
  49. data/doc/ex/blur_image.rb +12 -0
  50. data/doc/ex/border.rb +10 -0
  51. data/doc/ex/bounding_box.rb +42 -0
  52. data/doc/ex/cbezier1.rb +41 -0
  53. data/doc/ex/cbezier2.rb +41 -0
  54. data/doc/ex/cbezier3.rb +41 -0
  55. data/doc/ex/cbezier4.rb +42 -0
  56. data/doc/ex/cbezier5.rb +42 -0
  57. data/doc/ex/cbezier6.rb +53 -0
  58. data/doc/ex/channel.rb +25 -0
  59. data/doc/ex/charcoal.rb +12 -0
  60. data/doc/ex/chop.rb +29 -0
  61. data/doc/ex/circle.rb +33 -0
  62. data/doc/ex/circle01.rb +16 -0
  63. data/doc/ex/clip_path.rb +60 -0
  64. data/doc/ex/coalesce.rb +57 -0
  65. data/doc/ex/color_fill_to_border.rb +29 -0
  66. data/doc/ex/color_floodfill.rb +28 -0
  67. data/doc/ex/color_histogram.rb +47 -0
  68. data/doc/ex/color_reset.rb +11 -0
  69. data/doc/ex/colorize.rb +16 -0
  70. data/doc/ex/colors.rb +64 -0
  71. data/doc/ex/compose_mask.rb +22 -0
  72. data/doc/ex/composite.rb +133 -0
  73. data/doc/ex/composite_layers.rb +53 -0
  74. data/doc/ex/composite_tiled.rb +21 -0
  75. data/doc/ex/contrast.rb +36 -0
  76. data/doc/ex/crop.rb +31 -0
  77. data/doc/ex/crop_with_gravity.rb +42 -0
  78. data/doc/ex/cubic01.rb +43 -0
  79. data/doc/ex/cubic02.rb +91 -0
  80. data/doc/ex/cycle_colormap.rb +21 -0
  81. data/doc/ex/dissolve.rb +12 -0
  82. data/doc/ex/drawcomp.rb +42 -0
  83. data/doc/ex/drop_shadow.rb +60 -0
  84. data/doc/ex/edge.rb +11 -0
  85. data/doc/ex/ellipse.rb +45 -0
  86. data/doc/ex/ellipse01.rb +21 -0
  87. data/doc/ex/emboss.rb +11 -0
  88. data/doc/ex/enhance.rb +28 -0
  89. data/doc/ex/equalize.rb +11 -0
  90. data/doc/ex/evenodd.rb +42 -0
  91. data/doc/ex/fill_pattern.rb +23 -0
  92. data/doc/ex/flatten_images.rb +36 -0
  93. data/doc/ex/flip.rb +11 -0
  94. data/doc/ex/flop.rb +11 -0
  95. data/doc/ex/font_styles.rb +32 -0
  96. data/doc/ex/fonts.rb +20 -0
  97. data/doc/ex/frame.rb +12 -0
  98. data/doc/ex/gaussian_blur.rb +11 -0
  99. data/doc/ex/get_multiline_type_metrics.rb +41 -0
  100. data/doc/ex/get_pixels.rb +47 -0
  101. data/doc/ex/get_type_metrics.rb +141 -0
  102. data/doc/ex/gradientfill.rb +27 -0
  103. data/doc/ex/grav.rb +45 -0
  104. data/doc/ex/gravity.rb +80 -0
  105. data/doc/ex/group.rb +26 -0
  106. data/doc/ex/hatchfill.rb +27 -0
  107. data/doc/ex/image.rb +44 -0
  108. data/doc/ex/images/Apple.miff +0 -0
  109. data/doc/ex/images/Ballerina.jpg +0 -0
  110. data/doc/ex/images/Ballerina3.jpg +0 -0
  111. data/doc/ex/images/Button_0.gif +0 -0
  112. data/doc/ex/images/Button_1.gif +0 -0
  113. data/doc/ex/images/Button_2.gif +0 -0
  114. data/doc/ex/images/Button_3.gif +0 -0
  115. data/doc/ex/images/Button_4.gif +0 -0
  116. data/doc/ex/images/Button_5.gif +0 -0
  117. data/doc/ex/images/Button_6.gif +0 -0
  118. data/doc/ex/images/Button_7.gif +0 -0
  119. data/doc/ex/images/Button_8.gif +0 -0
  120. data/doc/ex/images/Button_9.gif +0 -0
  121. data/doc/ex/images/Button_A.gif +0 -0
  122. data/doc/ex/images/Button_B.gif +0 -0
  123. data/doc/ex/images/Button_C.gif +0 -0
  124. data/doc/ex/images/Button_D.gif +0 -0
  125. data/doc/ex/images/Button_E.gif +0 -0
  126. data/doc/ex/images/Button_F.gif +0 -0
  127. data/doc/ex/images/Button_G.gif +0 -0
  128. data/doc/ex/images/Button_H.gif +0 -0
  129. data/doc/ex/images/Button_I.gif +0 -0
  130. data/doc/ex/images/Button_J.gif +0 -0
  131. data/doc/ex/images/Button_K.gif +0 -0
  132. data/doc/ex/images/Button_L.gif +0 -0
  133. data/doc/ex/images/Button_M.gif +0 -0
  134. data/doc/ex/images/Button_N.gif +0 -0
  135. data/doc/ex/images/Button_O.gif +0 -0
  136. data/doc/ex/images/Button_P.gif +0 -0
  137. data/doc/ex/images/Button_Q.gif +0 -0
  138. data/doc/ex/images/Button_R.gif +0 -0
  139. data/doc/ex/images/Button_S.gif +0 -0
  140. data/doc/ex/images/Button_T.gif +0 -0
  141. data/doc/ex/images/Button_U.gif +0 -0
  142. data/doc/ex/images/Button_V.gif +0 -0
  143. data/doc/ex/images/Button_W.gif +0 -0
  144. data/doc/ex/images/Button_X.gif +0 -0
  145. data/doc/ex/images/Button_Y.gif +0 -0
  146. data/doc/ex/images/Button_Z.gif +0 -0
  147. data/doc/ex/images/Cheetah.jpg +0 -0
  148. data/doc/ex/images/Coffee.wmf +0 -0
  149. data/doc/ex/images/Flower_Hat.jpg +0 -0
  150. data/doc/ex/images/Gold_Statue.jpg +0 -0
  151. data/doc/ex/images/Hot_Air_Balloons.jpg +0 -0
  152. data/doc/ex/images/Hot_Air_Balloons_H.jpg +0 -0
  153. data/doc/ex/images/Leaf.miff +0 -0
  154. data/doc/ex/images/No.wmf +0 -0
  155. data/doc/ex/images/Polynesia.jpg +0 -0
  156. data/doc/ex/images/Red_Rocks.jpg +0 -0
  157. data/doc/ex/images/Rocks_On_Beach.miff +0 -0
  158. data/doc/ex/images/Shorts.jpg +0 -0
  159. data/doc/ex/images/Snake.wmf +0 -0
  160. data/doc/ex/images/Violin.jpg +0 -0
  161. data/doc/ex/images/Yellow_Rose.miff +0 -0
  162. data/doc/ex/images/big-duck.gif +0 -0
  163. data/doc/ex/images/duck.gif +0 -0
  164. data/doc/ex/images/duck0.gif +0 -0
  165. data/doc/ex/images/duck1.gif +0 -0
  166. data/doc/ex/images/duck10.gif +0 -0
  167. data/doc/ex/images/duck11.gif +0 -0
  168. data/doc/ex/images/duck12.gif +0 -0
  169. data/doc/ex/images/duck13.gif +0 -0
  170. data/doc/ex/images/duck14.gif +0 -0
  171. data/doc/ex/images/duck15.gif +0 -0
  172. data/doc/ex/images/duck2.gif +0 -0
  173. data/doc/ex/images/duck3.gif +0 -0
  174. data/doc/ex/images/duck4.gif +0 -0
  175. data/doc/ex/images/duck5.gif +0 -0
  176. data/doc/ex/images/duck6.gif +0 -0
  177. data/doc/ex/images/duck7.gif +0 -0
  178. data/doc/ex/images/duck8.gif +0 -0
  179. data/doc/ex/images/duck9.gif +0 -0
  180. data/doc/ex/images/graydient230x6.gif +0 -0
  181. data/doc/ex/images/image_with_profile.jpg +0 -0
  182. data/doc/ex/images/logo400x83.gif +0 -0
  183. data/doc/ex/images/model.miff +0 -0
  184. data/doc/ex/images/notimplemented.gif +0 -0
  185. data/doc/ex/images/smile.miff +0 -0
  186. data/doc/ex/images/spin.gif +0 -0
  187. data/doc/ex/implode.rb +34 -0
  188. data/doc/ex/level.rb +11 -0
  189. data/doc/ex/level_colors.rb +11 -0
  190. data/doc/ex/line.rb +41 -0
  191. data/doc/ex/line01.rb +21 -0
  192. data/doc/ex/mask.rb +35 -0
  193. data/doc/ex/matte_fill_to_border.rb +39 -0
  194. data/doc/ex/matte_floodfill.rb +32 -0
  195. data/doc/ex/matte_replace.rb +39 -0
  196. data/doc/ex/median_filter.rb +28 -0
  197. data/doc/ex/modulate.rb +11 -0
  198. data/doc/ex/mono.rb +23 -0
  199. data/doc/ex/morph.rb +25 -0
  200. data/doc/ex/mosaic.rb +35 -0
  201. data/doc/ex/motion_blur.rb +11 -0
  202. data/doc/ex/negate.rb +11 -0
  203. data/doc/ex/negate_channel.rb +9 -0
  204. data/doc/ex/nested_rvg.rb +21 -0
  205. data/doc/ex/nonzero.rb +42 -0
  206. data/doc/ex/normalize.rb +11 -0
  207. data/doc/ex/oil_paint.rb +11 -0
  208. data/doc/ex/opacity.rb +37 -0
  209. data/doc/ex/ordered_dither.rb +11 -0
  210. data/doc/ex/path.rb +63 -0
  211. data/doc/ex/pattern1.rb +25 -0
  212. data/doc/ex/pattern2.rb +26 -0
  213. data/doc/ex/polaroid.rb +27 -0
  214. data/doc/ex/polygon.rb +23 -0
  215. data/doc/ex/polygon01.rb +21 -0
  216. data/doc/ex/polyline.rb +22 -0
  217. data/doc/ex/polyline01.rb +21 -0
  218. data/doc/ex/posterize.rb +8 -0
  219. data/doc/ex/preview.rb +8 -0
  220. data/doc/ex/qbezierpath.rb +52 -0
  221. data/doc/ex/quad01.rb +34 -0
  222. data/doc/ex/quantize-m.rb +25 -0
  223. data/doc/ex/radial_blur.rb +9 -0
  224. data/doc/ex/raise.rb +8 -0
  225. data/doc/ex/random_threshold_channel.rb +13 -0
  226. data/doc/ex/rect01.rb +14 -0
  227. data/doc/ex/rect02.rb +20 -0
  228. data/doc/ex/rectangle.rb +34 -0
  229. data/doc/ex/reduce_noise.rb +28 -0
  230. data/doc/ex/remap.rb +11 -0
  231. data/doc/ex/remap_images.rb +19 -0
  232. data/doc/ex/resize_to_fill.rb +8 -0
  233. data/doc/ex/resize_to_fit.rb +8 -0
  234. data/doc/ex/roll.rb +9 -0
  235. data/doc/ex/rotate.rb +44 -0
  236. data/doc/ex/rotate_f.rb +14 -0
  237. data/doc/ex/roundrect.rb +33 -0
  238. data/doc/ex/rubyname.rb +30 -0
  239. data/doc/ex/rvg_clippath.rb +12 -0
  240. data/doc/ex/rvg_linecap.rb +42 -0
  241. data/doc/ex/rvg_linejoin.rb +40 -0
  242. data/doc/ex/rvg_opacity.rb +18 -0
  243. data/doc/ex/rvg_pattern.rb +26 -0
  244. data/doc/ex/rvg_stroke_dasharray.rb +11 -0
  245. data/doc/ex/segment.rb +11 -0
  246. data/doc/ex/sepiatone.rb +7 -0
  247. data/doc/ex/shade.rb +11 -0
  248. data/doc/ex/shadow.rb +30 -0
  249. data/doc/ex/shave.rb +15 -0
  250. data/doc/ex/shear.rb +10 -0
  251. data/doc/ex/sketch.rb +17 -0
  252. data/doc/ex/skewx.rb +51 -0
  253. data/doc/ex/skewy.rb +47 -0
  254. data/doc/ex/smile.rb +125 -0
  255. data/doc/ex/solarize.rb +11 -0
  256. data/doc/ex/sparse_color.rb +54 -0
  257. data/doc/ex/splice.rb +8 -0
  258. data/doc/ex/spread.rb +11 -0
  259. data/doc/ex/stegano.rb +55 -0
  260. data/doc/ex/stroke_dasharray.rb +42 -0
  261. data/doc/ex/stroke_fill.rb +10 -0
  262. data/doc/ex/stroke_linecap.rb +44 -0
  263. data/doc/ex/stroke_linejoin.rb +48 -0
  264. data/doc/ex/stroke_width.rb +49 -0
  265. data/doc/ex/swirl.rb +17 -0
  266. data/doc/ex/text.rb +37 -0
  267. data/doc/ex/text01.rb +16 -0
  268. data/doc/ex/text_align.rb +36 -0
  269. data/doc/ex/text_antialias.rb +37 -0
  270. data/doc/ex/text_styles.rb +19 -0
  271. data/doc/ex/text_undercolor.rb +28 -0
  272. data/doc/ex/texture_fill_to_border.rb +34 -0
  273. data/doc/ex/texture_floodfill.rb +32 -0
  274. data/doc/ex/texturefill.rb +24 -0
  275. data/doc/ex/threshold.rb +13 -0
  276. data/doc/ex/to_blob.rb +13 -0
  277. data/doc/ex/translate.rb +39 -0
  278. data/doc/ex/transparent.rb +38 -0
  279. data/doc/ex/transpose.rb +9 -0
  280. data/doc/ex/transverse.rb +9 -0
  281. data/doc/ex/tref01.rb +24 -0
  282. data/doc/ex/triangle01.rb +15 -0
  283. data/doc/ex/trim.rb +23 -0
  284. data/doc/ex/tspan01.rb +17 -0
  285. data/doc/ex/tspan02.rb +17 -0
  286. data/doc/ex/tspan03.rb +19 -0
  287. data/doc/ex/unsharp_mask.rb +28 -0
  288. data/doc/ex/viewex.rb +33 -0
  289. data/doc/ex/vignette.rb +12 -0
  290. data/doc/ex/watermark.rb +27 -0
  291. data/doc/ex/wave.rb +9 -0
  292. data/doc/ex/wet_floor.rb +58 -0
  293. data/doc/ex/writing_mode01.rb +26 -0
  294. data/doc/ex/writing_mode02.rb +26 -0
  295. data/doc/ilist.html +2056 -0
  296. data/doc/image1.html +4680 -0
  297. data/doc/image2.html +3665 -0
  298. data/doc/image3.html +4522 -0
  299. data/doc/imageattrs.html +1638 -0
  300. data/doc/imusage.html +514 -0
  301. data/doc/index.html +416 -0
  302. data/doc/info.html +1499 -0
  303. data/doc/magick.html +565 -0
  304. data/doc/optequiv.html +2435 -0
  305. data/doc/rvg.html +975 -0
  306. data/doc/rvgclip.html +248 -0
  307. data/doc/rvggroup.html +305 -0
  308. data/doc/rvgimage.html +289 -0
  309. data/doc/rvgpattern.html +475 -0
  310. data/doc/rvgshape.html +406 -0
  311. data/doc/rvgstyle.html +270 -0
  312. data/doc/rvgtext.html +465 -0
  313. data/doc/rvgtspan.html +238 -0
  314. data/doc/rvgtut.html +530 -0
  315. data/doc/rvguse.html +145 -0
  316. data/doc/rvgxform.html +294 -0
  317. data/doc/scripts/doc.js +22 -0
  318. data/doc/scripts/stripeTables.js +23 -0
  319. data/doc/struct.html +1339 -0
  320. data/doc/usage.html +1621 -0
  321. data/examples/constitute.rb +7 -0
  322. data/examples/crop_with_gravity.rb +42 -0
  323. data/examples/demo.rb +324 -0
  324. data/examples/describe.rb +43 -0
  325. data/examples/find_similar_region.rb +34 -0
  326. data/examples/histogram.rb +321 -0
  327. data/examples/identify.rb +185 -0
  328. data/examples/image_opacity.rb +29 -0
  329. data/examples/import_export.rb +31 -0
  330. data/examples/pattern_fill.rb +38 -0
  331. data/examples/rotating_text.rb +44 -0
  332. data/examples/spinner.rb +49 -0
  333. data/examples/thumbnail.rb +64 -0
  334. data/examples/vignette.rb +78 -0
  335. data/ext/RMagick/extconf.rb +548 -0
  336. data/ext/RMagick/rmagick.c +401 -0
  337. data/ext/RMagick/rmagick.h +1287 -0
  338. data/ext/RMagick/rmdraw.c +2022 -0
  339. data/ext/RMagick/rmenum.c +1235 -0
  340. data/ext/RMagick/rmfill.c +720 -0
  341. data/ext/RMagick/rmilist.c +1270 -0
  342. data/ext/RMagick/rmimage.c +15427 -0
  343. data/ext/RMagick/rminfo.c +2590 -0
  344. data/ext/RMagick/rmmain.c +1741 -0
  345. data/ext/RMagick/rmmontage.c +519 -0
  346. data/ext/RMagick/rmpixel.c +1114 -0
  347. data/ext/RMagick/rmstruct.c +1124 -0
  348. data/ext/RMagick/rmutil.c +1754 -0
  349. data/lib/rmagick.rb +1 -0
  350. data/lib/rmagick/version.rb +6 -0
  351. data/lib/rmagick_internal.rb +1947 -0
  352. data/lib/rvg/clippath.rb +45 -0
  353. data/lib/rvg/container.rb +122 -0
  354. data/lib/rvg/deep_equal.rb +52 -0
  355. data/lib/rvg/describable.rb +47 -0
  356. data/lib/rvg/embellishable.rb +391 -0
  357. data/lib/rvg/misc.rb +723 -0
  358. data/lib/rvg/paint.rb +50 -0
  359. data/lib/rvg/pathdata.rb +126 -0
  360. data/lib/rvg/rvg.rb +283 -0
  361. data/lib/rvg/stretchable.rb +165 -0
  362. data/lib/rvg/stylable.rb +116 -0
  363. data/lib/rvg/text.rb +172 -0
  364. data/lib/rvg/transformable.rb +126 -0
  365. data/lib/rvg/units.rb +63 -0
  366. data/rmagick.gemspec +46 -0
  367. data/spec/rmagick/ImageList1_spec.rb +24 -0
  368. data/spec/rmagick/draw_spec.rb +156 -0
  369. data/spec/rmagick/image/blue_shift_spec.rb +16 -0
  370. data/spec/rmagick/image/composite_spec.rb +140 -0
  371. data/spec/rmagick/image/constitute_spec.rb +15 -0
  372. data/spec/rmagick/image/dispatch_spec.rb +18 -0
  373. data/spec/rmagick/image/from_blob_spec.rb +14 -0
  374. data/spec/rmagick/image/ping_spec.rb +14 -0
  375. data/spec/rmagick/image/properties_spec.rb +29 -0
  376. data/spec/spec_helper.rb +4 -0
  377. data/test/Image1.rb +565 -0
  378. data/test/Image2.rb +1304 -0
  379. data/test/Image3.rb +1030 -0
  380. data/test/ImageList1.rb +806 -0
  381. data/test/ImageList2.rb +385 -0
  382. data/test/Image_attributes.rb +697 -0
  383. data/test/Import_Export.rb +121 -0
  384. data/test/Info.rb +345 -0
  385. data/test/Magick.rb +321 -0
  386. data/test/Pixel.rb +116 -0
  387. data/test/Preview.rb +57 -0
  388. data/test/cmyk.icm +0 -0
  389. data/test/srgb.icm +0 -0
  390. data/test/test_all_basic.rb +38 -0
  391. data/test/tmpnam_test.rb +50 -0
  392. data/wercker.yml +10 -0
  393. metadata +509 -0
@@ -0,0 +1,1754 @@
1
+ /**************************************************************************//**
2
+ * Utility functions for RMagick.
3
+ *
4
+ * Copyright © 2002 - 2009 by Timothy P. Hunter
5
+ *
6
+ * Changes since Nov. 2009 copyright © by Benjamin Thomas and Omer Bar-or
7
+ *
8
+ * @file rmutil.c
9
+ * @version $Id: rmutil.c,v 1.182 2009/12/21 10:34:58 baror Exp $
10
+ * @author Tim Hunter
11
+ ******************************************************************************/
12
+
13
+ #include "rmagick.h"
14
+ #include <errno.h>
15
+
16
+ static void handle_exception(ExceptionInfo *, Image *, ErrorRetention);
17
+
18
+
19
+ /**
20
+ * ImageMagick safe version of malloc.
21
+ *
22
+ * No Ruby usage (internal function)
23
+ *
24
+ * Notes:
25
+ * - Use when managing memory that ImageMagick may have allocated or may free.
26
+ * - If malloc fails, it raises an exception.
27
+ * - magick_safe_malloc and magick_safe_realloc prevent exceptions caused by
28
+ * integer overflow. Added in 6.3.5-9 but backwards compatible with prior
29
+ * releases.
30
+ *
31
+ * @param count the number of quantum elements to allocate
32
+ * @param quantum the number of bytes in each quantum
33
+ * @return a pointer to a block of memory that is at least count*quantum
34
+ */
35
+ void *
36
+ magick_safe_malloc(const size_t count, const size_t quantum)
37
+ {
38
+ void *ptr;
39
+
40
+ ptr = AcquireQuantumMemory(count, quantum);
41
+ if (!ptr)
42
+ {
43
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
44
+ }
45
+ return ptr;
46
+ }
47
+
48
+
49
+ /**
50
+ * ImageMagick version of malloc.
51
+ *
52
+ * No Ruby usage (internal function)
53
+ *
54
+ * @param size the size of memory to allocate
55
+ * @return pointer to a block of memory
56
+ */
57
+ void *
58
+ magick_malloc(const size_t size)
59
+ {
60
+ void *ptr;
61
+ ptr = AcquireMagickMemory(size);
62
+ if (!ptr)
63
+ {
64
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
65
+ }
66
+
67
+ return ptr;
68
+ }
69
+
70
+
71
+ /**
72
+ * ImageMagick version of free.
73
+ *
74
+ * No Ruby usage (internal function)
75
+ *
76
+ * @param ptr pointer to the existing block of memory
77
+ */
78
+ void
79
+ magick_free(void *ptr)
80
+ {
81
+ (void) RelinquishMagickMemory(ptr);
82
+ }
83
+
84
+
85
+ /**
86
+ * ImageMagick safe version of realloc.
87
+ *
88
+ * No Ruby usage (internal function)
89
+ *
90
+ * Notes:
91
+ * - Use when managing memory that ImageMagick may have allocated or may free.
92
+ * - If malloc fails, it raises an exception.
93
+ * - magick_safe_malloc and magick_safe_realloc prevent exceptions caused by
94
+ * integer overflow. Added in 6.3.5-9 but backwards compatible with prior
95
+ * releases.
96
+ *
97
+ * @param memory the existing block of memory
98
+ * @param count the number of quantum elements to allocate
99
+ * @param quantum the number of bytes in each quantum
100
+ * @return a pointer to a block of memory that is at least count*quantum in size
101
+ */
102
+ void *
103
+ magick_safe_realloc(void *memory, const size_t count, const size_t quantum)
104
+ {
105
+ void *v;
106
+ v = ResizeQuantumMemory(memory, count, quantum);
107
+ if (!v)
108
+ {
109
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
110
+ }
111
+ return v;
112
+ }
113
+
114
+
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
+ /**
138
+ * Make a copy of a string in malloc'd memory.
139
+ *
140
+ * No Ruby usage (internal function)
141
+ *
142
+ * Notes:
143
+ * - Any existing string pointed to by *new_str is freed.
144
+ * - CloneString asserts if no memory. No need to check its return value.
145
+ *
146
+ * @param new_str pointer to the new string
147
+ * @param str the string to copy
148
+ */
149
+ void
150
+ magick_clone_string(char **new_str, const char *str)
151
+ {
152
+ (void) CloneString(new_str, str);
153
+ }
154
+
155
+
156
+ /**
157
+ * Compare s1 and s2 ignoring case.
158
+ *
159
+ * No Ruby usage (internal function)
160
+ *
161
+ * @param s1 the first string
162
+ * @param s2 the second string
163
+ * @return same as strcmp(3)
164
+ */
165
+ int
166
+ rm_strcasecmp(const char *s1, const char *s2)
167
+ {
168
+ while (*s1 && *s2)
169
+ {
170
+ if (toupper(*s1) != toupper(*s2))
171
+ {
172
+ break;
173
+ }
174
+ s1 += 1;
175
+ s2 += 1;
176
+ }
177
+ return (int)(*s1 - *s2);
178
+ }
179
+
180
+
181
+ /**
182
+ * Compare s1 and s2 ignoring case.
183
+ *
184
+ * No Ruby usage (internal function)
185
+ *
186
+ * @param s1 the first string
187
+ * @param s2 the second string
188
+ * @param n number of characters to compare
189
+ * @return same as strcmp(3)
190
+ */
191
+ int
192
+ rm_strncasecmp(const char *s1, const char *s2, size_t n)
193
+ {
194
+ if (n == 0)
195
+ {
196
+ return 0;
197
+ }
198
+ while (toupper(*s1) == toupper(*s2))
199
+ {
200
+ if (--n == 0 || *s1 == '\0')
201
+ {
202
+ return 0;
203
+ }
204
+ s1 += 1;
205
+ s2 += 1;
206
+ }
207
+ return (int)(*s1 - *s2);
208
+ }
209
+
210
+
211
+ /**
212
+ * Raise exception if array too short.
213
+ *
214
+ * No Ruby usage (internal function)
215
+ *
216
+ * @param ary the array
217
+ * @param len the minimum length
218
+ * @throw IndexError
219
+ */
220
+ void
221
+ rm_check_ary_len(VALUE ary, long len)
222
+ {
223
+ if (RARRAY_LEN(ary) < len)
224
+ {
225
+ rb_raise(rb_eIndexError, "not enough elements in array - expecting %ld, got %ld",
226
+ len, (long)RARRAY_LEN(ary));
227
+ }
228
+ }
229
+
230
+
231
+ /**
232
+ * Raise an error if the image has been destroyed.
233
+ *
234
+ * No Ruby usage (internal function)
235
+ *
236
+ * @param obj the image
237
+ * @return the C image structure for the image
238
+ * @throw DestroyedImageError
239
+ */
240
+ Image *
241
+ rm_check_destroyed(VALUE obj)
242
+ {
243
+ Image *image;
244
+
245
+ Data_Get_Struct(obj, Image, image);
246
+ if (!image)
247
+ {
248
+ rb_raise(Class_DestroyedImageError, "destroyed image");
249
+ }
250
+
251
+ return image;
252
+ }
253
+
254
+
255
+ /**
256
+ * Raise an error if the image has been destroyed or is frozen.
257
+ *
258
+ * No Ruby usage (internal function)
259
+ *
260
+ * @param obj the image
261
+ * @return the C image structure for the image
262
+ */
263
+ Image *
264
+ rm_check_frozen(VALUE obj)
265
+ {
266
+ Image *image = rm_check_destroyed(obj);
267
+ rb_check_frozen(obj);
268
+ return image;
269
+ }
270
+
271
+
272
+ /**
273
+ * Overrides freeze in classes that can't be frozen.
274
+ *
275
+ * No Ruby usage (internal function)
276
+ *
277
+ * @param obj the object of the class to override
278
+ * @return 0
279
+ * @throw TypeError
280
+ */
281
+ VALUE
282
+ rm_no_freeze(VALUE obj)
283
+ {
284
+ 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
+ }
307
+
308
+
309
+ /**
310
+ * Supply our own version of the "obsolete" rb_str2cstr.
311
+ *
312
+ * No Ruby usage (internal function)
313
+ *
314
+ * @param str the Ruby string
315
+ * @param len pointer to a long in which to store the number of characters
316
+ * @return a C string version of str
317
+ */
318
+ char *
319
+ rm_str2cstr(VALUE str, long *len)
320
+ {
321
+ StringValue(str);
322
+ if (len)
323
+ {
324
+ *len = RSTRING_LEN(str);
325
+ }
326
+ return RSTRING_PTR(str);
327
+ }
328
+
329
+
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
+ /**
349
+ * Called when `rb_str_to_str' raises an exception.
350
+ *
351
+ * No Ruby usage (internal function)
352
+ *
353
+ * @param arg the argument
354
+ * @return 0
355
+ * @throw TypeError
356
+ */
357
+ static VALUE
358
+ rescue_not_str(VALUE arg)
359
+ {
360
+ rb_raise(rb_eTypeError, "argument must be a number or a string in the form 'NN%%' (%s given)",
361
+ rb_class2name(CLASS_OF(arg)));
362
+ return (VALUE)0;
363
+ }
364
+
365
+
366
+ /**
367
+ * Return a double between 0.0 and max (the second argument), inclusive. If the
368
+ * argument is a number convert to a Float object, otherwise it's supposed to be
369
+ * a string in the form * "NN%". Convert to a number and then to a Float.
370
+ *
371
+ * No Ruby usage (internal function)
372
+ *
373
+ * @param arg the argument
374
+ * @param max the maximum allowed value
375
+ * @return a double
376
+ */
377
+ double
378
+ rm_percentage(VALUE arg, double max)
379
+ {
380
+ 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);
387
+
388
+ if (not_num)
389
+ {
390
+ arg = rb_rescue(rb_str_to_str, arg, rescue_not_str, arg);
391
+ pct_str = StringValuePtr(arg);
392
+ errno = 0;
393
+ pct_long = strtol(pct_str, &end, 10);
394
+ if (errno == ERANGE)
395
+ {
396
+ rb_raise(rb_eRangeError, "`%s' out of range", pct_str);
397
+ }
398
+ if (*end != '\0' && *end != '%')
399
+ {
400
+ rb_raise(rb_eArgError, "expected percentage, got `%s'", pct_str);
401
+ }
402
+
403
+ if (*end == '%' && pct_long != 0)
404
+ {
405
+ pct = (((double)pct_long) / 100.0) * max;
406
+ }
407
+ else
408
+ {
409
+ pct = (double) pct_long;
410
+ }
411
+ if (pct < 0.0)
412
+ {
413
+ rb_raise(rb_eArgError, "percentages may not be negative (got `%s')", pct_str);
414
+ }
415
+ }
416
+ else
417
+ {
418
+ pct = NUM2DBL(arg);
419
+ if (pct < 0.0)
420
+ {
421
+ rb_raise(rb_eArgError, "percentages may not be negative (got `%g')", pct);
422
+ }
423
+ }
424
+
425
+ return pct;
426
+ }
427
+
428
+
429
+ /**
430
+ * Return 0 if rb_num2dbl doesn't raise an exception.
431
+ *
432
+ * No Ruby usage (internal function)
433
+ *
434
+ * @param obj the object to convert to a double
435
+ * @return 0
436
+ */
437
+ static VALUE
438
+ check_num2dbl(VALUE obj)
439
+ {
440
+ (void) rb_num2dbl(obj);
441
+ return INT2FIX(1);
442
+ }
443
+
444
+
445
+ /**
446
+ * Called if rb_num2dbl raises an exception.
447
+ *
448
+ * No Ruby usage (internal function)
449
+ *
450
+ * @param ignored a Ruby object (unused)
451
+ * @return 0
452
+ */
453
+ static VALUE
454
+ rescue_not_dbl(VALUE ignored)
455
+ {
456
+ ignored = ignored; // defeat gcc message
457
+ return INT2FIX(0);
458
+ }
459
+
460
+
461
+ /**
462
+ * Return 1 if the object can be converted to a double, 0 otherwise.
463
+ *
464
+ * No Ruby usage (internal function)
465
+ *
466
+ * @param obj the object
467
+ * @return 1 or 0
468
+ */
469
+ int
470
+ rm_check_num2dbl(VALUE obj)
471
+ {
472
+ return FIX2INT(rb_rescue(check_num2dbl, obj, rescue_not_dbl, (VALUE)0));
473
+ }
474
+
475
+
476
+ /**
477
+ * Given a string in the form NN% return the corresponding double.
478
+ *
479
+ * No Ruby usage (internal function)
480
+ *
481
+ * @param str the string
482
+ * @return a double
483
+ */
484
+ double
485
+ rm_str_to_pct(VALUE str)
486
+ {
487
+ long pct;
488
+ char *pct_str, *end;
489
+
490
+ str = rb_rescue(rb_str_to_str, str, rescue_not_str, str);
491
+ pct_str = StringValuePtr(str);
492
+ errno = 0;
493
+ pct = strtol(pct_str, &end, 10);
494
+
495
+ if (errno == ERANGE)
496
+ {
497
+ rb_raise(rb_eRangeError, "`%s' out of range", pct_str);
498
+ }
499
+ if (*end != '%')
500
+ {
501
+ rb_raise(rb_eArgError, "expected percentage, got `%s'", pct_str);
502
+ }
503
+ if (pct < 0L)
504
+ {
505
+ rb_raise(rb_eArgError, "percentages may not be negative (got `%s')", pct_str);
506
+ }
507
+
508
+ return pct / 100.0;
509
+ }
510
+
511
+
512
+ /**
513
+ * If the argument is a number, convert it to a double. Otherwise it's supposed
514
+ * to be a string in the form 'NN%'. Return a percentage of QuantumRange.
515
+ *
516
+ * No Ruby usage (internal function)
517
+ *
518
+ * @param fuzz_arg the fuzz argument
519
+ * @return a double
520
+ * @see Image_fuzz
521
+ * @see Image_fuzz_eq
522
+ */
523
+ double
524
+ rm_fuzz_to_dbl(VALUE fuzz_arg)
525
+ {
526
+ 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);
532
+
533
+ if (not_num)
534
+ {
535
+ // Convert to string, issue error message if failure.
536
+ fuzz_arg = rb_rescue(rb_str_to_str, fuzz_arg, rescue_not_str, fuzz_arg);
537
+ fuzz_str = StringValuePtr(fuzz_arg);
538
+ errno = 0;
539
+ fuzz = strtod(fuzz_str, &end);
540
+ if (errno == ERANGE)
541
+ {
542
+ rb_raise(rb_eRangeError, "`%s' out of range", fuzz_str);
543
+ }
544
+ if(*end == '%')
545
+ {
546
+ if (fuzz < 0.0)
547
+ {
548
+ rb_raise(rb_eArgError, "percentages may not be negative (got `%s')", fuzz_str);
549
+ }
550
+ fuzz = (fuzz * QuantumRange) / 100.0;
551
+ }
552
+ else if(*end != '\0')
553
+ {
554
+ rb_raise(rb_eArgError, "expected percentage, got `%s'", fuzz_str);
555
+ }
556
+ }
557
+ else
558
+ {
559
+ fuzz = NUM2DBL(fuzz_arg);
560
+ if (fuzz < 0.0)
561
+ {
562
+ rb_raise(rb_eArgError, "fuzz may not be negative (got `%g')", fuzz);
563
+ }
564
+ }
565
+
566
+ return fuzz;
567
+ }
568
+
569
+
570
+ /**
571
+ * Convert a application-supplied number to a Quantum. If the object is a Float,
572
+ * truncate it before converting.
573
+ *
574
+ * No Ruby usage (internal function)
575
+ *
576
+ * Notes:
577
+ * - Ruby says that 2147483647.5 doesn't fit into an unsigned long. If you
578
+ * truncate it, it works.
579
+ * - Should use this only when the input value is possibly subject to this
580
+ * problem.
581
+ *
582
+ * @param obj the application-supplied number
583
+ * @return a Quantum
584
+ */
585
+ Quantum
586
+ rm_app2quantum(VALUE obj)
587
+ {
588
+ VALUE v = obj;
589
+
590
+ if (TYPE(obj) == T_FLOAT)
591
+ {
592
+ v = rb_funcall(obj, rm_ID_to_i, 0);
593
+ }
594
+
595
+ RB_GC_GUARD(v);
596
+
597
+ return NUM2QUANTUM(v);
598
+ }
599
+
600
+
601
+ /**
602
+ * Send the "cur_image" method to the object. If 'img' is an ImageList, then
603
+ * cur_image is self[\@scene]. If 'img' is an image, then cur_image is simply
604
+ * 'self'.
605
+ *
606
+ * No Ruby usage (internal function)
607
+ *
608
+ * @param img the object
609
+ * @return the return value from "cur_image"
610
+ */
611
+ VALUE
612
+ rm_cur_image(VALUE img)
613
+ {
614
+ return rb_funcall(img, rm_ID_cur_image, 0);
615
+ }
616
+
617
+
618
+ /**
619
+ * Map the color intensity to a named color.
620
+ *
621
+ * No Ruby usage (internal function)
622
+ *
623
+ * @param image the image
624
+ * @param color the color intensity as a PixelPacket
625
+ * @return the named color as a String
626
+ * @see rm_pixelpacket_to_color_name_info
627
+ */
628
+ VALUE
629
+ rm_pixelpacket_to_color_name(Image *image, PixelPacket *color)
630
+ {
631
+ char name[MaxTextExtent];
632
+ ExceptionInfo *exception;
633
+
634
+ exception = AcquireExceptionInfo();
635
+
636
+ (void) QueryColorname(image, color, X11Compliance, name, exception);
637
+ CHECK_EXCEPTION()
638
+ (void) DestroyExceptionInfo(exception);
639
+
640
+ return rb_str_new2(name);
641
+ }
642
+
643
+
644
+ /**
645
+ * Map the color intensity to a named color.
646
+ *
647
+ * No Ruby usage (internal function)
648
+ *
649
+ * Notes:
650
+ * - Simply create an Image from the Info, call QueryColorname, and then
651
+ * destroy the Image.
652
+ * - If the Info structure is NULL, creates a new one.
653
+ * - The default depth is always used, and the matte value is set to False,
654
+ * which means "don't use the alpha channel".
655
+ *
656
+ * @param info the info
657
+ * @param color the color intensity as a PixelPacket
658
+ * @return the named color as a String
659
+ * @see rm_pixelpacket_to_color_name
660
+ */
661
+ VALUE
662
+ rm_pixelpacket_to_color_name_info(Info *info, PixelPacket *color)
663
+ {
664
+ Image *image;
665
+ Info *my_info;
666
+ VALUE color_name;
667
+
668
+ my_info = info ? info : CloneImageInfo(NULL);
669
+
670
+ image = AcquireImage(info);
671
+ image->matte = MagickFalse;
672
+ color_name = rm_pixelpacket_to_color_name(image, color);
673
+ (void) DestroyImage(image);
674
+ if (!info)
675
+ {
676
+ (void) DestroyImageInfo(my_info);
677
+ }
678
+
679
+ RB_GC_GUARD(color_name);
680
+
681
+ return color_name;
682
+ }
683
+
684
+
685
+ /**
686
+ * Write a temporary copy of the image to the IM registry.
687
+ *
688
+ * No Ruby usage (internal function)
689
+ *
690
+ * Notes:
691
+ * - The `temp_name' argument must point to an char array of size
692
+ * MaxTextExtent.
693
+ *
694
+ * @param image the image
695
+ * @param temp_name the temporary name to use
696
+ * @return the "filename" of the registered image
697
+ */
698
+ void
699
+ rm_write_temp_image(Image *image, char *temp_name)
700
+ {
701
+
702
+ #define TMPNAM_CLASS_VAR "@@_tmpnam_"
703
+
704
+ MagickBooleanType okay;
705
+ ExceptionInfo *exception;
706
+ VALUE id_value;
707
+ int id;
708
+
709
+ exception = AcquireExceptionInfo();
710
+
711
+
712
+ // 'id' is always the value of its previous use
713
+ if (rb_cvar_defined(Module_Magick, rb_intern(TMPNAM_CLASS_VAR)) == Qtrue)
714
+ {
715
+ id_value = rb_cv_get(Module_Magick, TMPNAM_CLASS_VAR);
716
+ id = FIX2INT(id_value);
717
+ }
718
+ else
719
+ {
720
+ id = 0;
721
+ rb_cv_set(Module_Magick, TMPNAM_CLASS_VAR, INT2FIX(id));
722
+ }
723
+
724
+ id += 1;
725
+ rb_cv_set(Module_Magick, TMPNAM_CLASS_VAR, INT2FIX(id));
726
+ sprintf(temp_name, "mpri:%d", id);
727
+
728
+ // Omit "mpri:" from filename to form the key
729
+ okay = SetImageRegistry(ImageRegistryType, temp_name+5, image, exception);
730
+ CHECK_EXCEPTION()
731
+ DestroyExceptionInfo(exception);
732
+ if (!okay)
733
+ {
734
+ rb_raise(rb_eRuntimeError, "SetImageRegistry failed.");
735
+ }
736
+
737
+ RB_GC_GUARD(id_value);
738
+ }
739
+
740
+
741
+ /**
742
+ * Delete the temporary image from the registry.
743
+ *
744
+ * No Ruby usage (internal function)
745
+ *
746
+ * @param temp_name the name of temporary image in the registry.
747
+ */
748
+ void
749
+ rm_delete_temp_image(char *temp_name)
750
+ {
751
+ MagickBooleanType okay = DeleteImageRegistry(temp_name+5);
752
+
753
+ if (!okay)
754
+ {
755
+ rb_warn("DeleteImageRegistry failed for `%s'", temp_name);
756
+ }
757
+ }
758
+
759
+
760
+ /**
761
+ * Raise NotImplementedError.
762
+ *
763
+ * No Ruby usage (internal function)
764
+ *
765
+ * Notes:
766
+ * - Called when a xMagick API is not available.
767
+ * - Replaces Ruby's rb_notimplement function.
768
+ *
769
+ * @throw NotImpError
770
+ */
771
+ void
772
+ rm_not_implemented(void)
773
+ {
774
+
775
+ rb_raise(rb_eNotImpError, "the `%s' method is not supported by ImageMagick "
776
+ MagickLibVersionText, rb_id2name(THIS_FUNC()));
777
+ }
778
+
779
+
780
+ /**
781
+ * Create a new ImageMagickError object and raise an exception.
782
+ *
783
+ * No Ruby usage (internal function)
784
+ *
785
+ * Notes:
786
+ * - This funky technique allows me to safely add additional information to
787
+ * the ImageMagickError object in both 1.6.8 and 1.8.0.
788
+ *
789
+ * @param msg the error mesage
790
+ * @param loc the location of the error
791
+ * @throw ImageMagickError
792
+ * @see www.ruby_talk.org/36408.
793
+ */
794
+ void
795
+ rm_magick_error(const char *msg, const char *loc)
796
+ {
797
+ VALUE exc, mesg, extra;
798
+
799
+ mesg = rb_str_new2(msg);
800
+ extra = loc ? rb_str_new2(loc) : Qnil;
801
+
802
+ exc = rb_funcall(Class_ImageMagickError, rm_ID_new, 2, mesg, extra);
803
+ (void) rb_funcall(rb_cObject, rb_intern("raise"), 1, exc);
804
+
805
+ RB_GC_GUARD(exc);
806
+ RB_GC_GUARD(mesg);
807
+ RB_GC_GUARD(extra);
808
+ }
809
+
810
+
811
+ /**
812
+ * Initialize a new ImageMagickError object - store the "loc" string in the
813
+ * \@magick_location instance variable.
814
+ *
815
+ * Ruby usage:
816
+ * - @verbatim ImageMagickError#initialize(msg) @endverbatim
817
+ * - @verbatim ImageMagickError#initialize(msg, loc) @endverbatim
818
+ *
819
+ * Notes:
820
+ * - Default loc is nil
821
+ *
822
+ * @param argc number of input arguments
823
+ * @param argv array of input arguments
824
+ * @param self this object
825
+ * @return self
826
+ */
827
+ VALUE
828
+ ImageMagickError_initialize(int argc, VALUE *argv, VALUE self)
829
+ {
830
+ VALUE super_argv[1] = {(VALUE)0};
831
+ int super_argc = 0;
832
+ VALUE extra = Qnil;
833
+
834
+ switch(argc)
835
+ {
836
+ case 2:
837
+ extra = argv[1];
838
+ case 1:
839
+ super_argv[0] = argv[0];
840
+ super_argc = 1;
841
+ case 0:
842
+ break;
843
+ default:
844
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 to 2)", argc);
845
+ }
846
+
847
+ (void) rb_call_super(super_argc, (const VALUE *)super_argv);
848
+ (void) rb_iv_set(self, "@"MAGICK_LOC, extra);
849
+
850
+ RB_GC_GUARD(extra);
851
+
852
+ return self;
853
+ }
854
+
855
+
856
+ /**
857
+ * Backport GetImageProperty for pre-6.3.1 versions of ImageMagick.
858
+ *
859
+ * No Ruby usage (internal function)
860
+ *
861
+ * @param img the image
862
+ * @param property the property name
863
+ * @return the property value
864
+ */
865
+ const char *
866
+ rm_get_property(const Image *img, const char *property)
867
+ {
868
+ return GetImageProperty(img, property);
869
+ }
870
+
871
+
872
+ /**
873
+ * Backport SetImageProperty for pre-6.3.1 versions of ImageMagick.
874
+ *
875
+ * No Ruby usage (internal function)
876
+ *
877
+ * @param image the image
878
+ * @param property the property name
879
+ * @param value the property value
880
+ * @return true if successful, otherwise false
881
+ */
882
+ MagickBooleanType
883
+ rm_set_property(Image *image, const char *property, const char *value)
884
+ {
885
+ return SetImageProperty(image, property, value);
886
+ }
887
+
888
+
889
+ /**
890
+ * If a "user" option is present in the Info, assign its value to a "user"
891
+ * artifact in each image.
892
+ *
893
+ * No Ruby usage (internal function)
894
+ *
895
+ * @param images a list of images
896
+ * @param info the info
897
+ */
898
+ void rm_set_user_artifact(Image *images, Info *info)
899
+ {
900
+ #if defined(HAVE_SETIMAGEARTIFACT)
901
+ Image *image;
902
+ const char *value;
903
+
904
+ value = GetImageOption(info, "user");
905
+ if (value)
906
+ {
907
+ image = GetFirstImageInList(images);
908
+ while (image)
909
+ {
910
+ (void) SetImageArtifact(image, "user", value);
911
+ image = GetNextImageInList(image);
912
+ }
913
+ }
914
+ #else
915
+ images = images;
916
+ info = info;
917
+ #endif
918
+ }
919
+
920
+
921
+ /**
922
+ * Collect optional method arguments via Magick::OptionalMethodArguments.
923
+ *
924
+ * No Ruby usage (internal function)
925
+ *
926
+ * Notes:
927
+ * - Creates an instance of Magick::OptionalMethodArguments, then yields to a
928
+ * block in the context of the instance.
929
+ *
930
+ * @param img the image
931
+ */
932
+ void
933
+ rm_get_optional_arguments(VALUE img)
934
+ {
935
+ VALUE optional_method_arguments;
936
+ VALUE opt_args;
937
+ VALUE argv[1];
938
+
939
+ // opt_args = Magick::OptionalMethodArguments.new(img)
940
+ // opt_args.instance_eval { block }
941
+ if (rb_block_given_p())
942
+ {
943
+ optional_method_arguments = rb_const_get_from(Module_Magick, rb_intern("OptionalMethodArguments"));
944
+ argv[0] = img;
945
+ opt_args = rb_class_new_instance(1, argv, optional_method_arguments);
946
+ (void) rb_obj_instance_eval(0, NULL, opt_args);
947
+ }
948
+
949
+ RB_GC_GUARD(optional_method_arguments);
950
+ RB_GC_GUARD(opt_args);
951
+
952
+ return;
953
+ }
954
+
955
+
956
+ #if defined(HAVE_SETIMAGEARTIFACT)
957
+ /**
958
+ * Copy image options from the Info structure to the Image structure.
959
+ *
960
+ * No Ruby usage (internal function)
961
+ *
962
+ * @param image the Image structure to modify
963
+ * @param info the Info structure
964
+ */
965
+ static void copy_options(Image *image, Info *info)
966
+ {
967
+ char property[MaxTextExtent];
968
+ const char *value, *option;
969
+
970
+ ResetImageOptionIterator(info);
971
+ for (option = GetNextImageOption(info); option; option = GetNextImageOption(info))
972
+ {
973
+ value = GetImageOption(info,option);
974
+ if (value)
975
+ {
976
+ strncpy(property, value, MaxTextExtent);
977
+ property[MaxTextExtent-1] = '\0';
978
+ (void) SetImageArtifact(image, property, value);
979
+ }
980
+ }
981
+ }
982
+ #endif
983
+
984
+
985
+ /**
986
+ * Propagate ImageInfo values to the Image
987
+ *
988
+ * No Ruby usage (internal function)
989
+ *
990
+ * @param image the Image structure to modify
991
+ * @param info the Info structure
992
+ * @see SyncImageSettings in mogrify.c in ImageMagick
993
+ */
994
+ void rm_sync_image_options(Image *image, Info *info)
995
+ {
996
+ MagickStatusType flags;
997
+ GeometryInfo geometry_info;
998
+ const char *option;
999
+
1000
+ // The option strings will be set only when their attribute values were
1001
+ // set in the optional argument block.
1002
+ option = GetImageOption(info,"background");
1003
+ if (option)
1004
+ {
1005
+ image->background_color = info->background_color;
1006
+ }
1007
+
1008
+ option = GetImageOption(info,"bordercolor");
1009
+ if (option)
1010
+ {
1011
+ image->border_color = info->border_color;
1012
+ }
1013
+
1014
+ if (info->colorspace != UndefinedColorspace)
1015
+ {
1016
+ image->colorspace = info->colorspace;
1017
+ }
1018
+
1019
+ if (info->compression != UndefinedCompression)
1020
+ {
1021
+ image->compression = info->compression;
1022
+ }
1023
+
1024
+ option = GetImageOption(info, "delay");
1025
+ if (option)
1026
+ {
1027
+ image->delay = strtoul(option, NULL, 0);
1028
+ }
1029
+
1030
+ if (info->density)
1031
+ {
1032
+ flags = ParseGeometry(info->density, &geometry_info);
1033
+ image->x_resolution = geometry_info.rho;
1034
+ image->y_resolution = geometry_info.sigma;
1035
+ if ((flags & SigmaValue) == 0)
1036
+ {
1037
+ image->y_resolution = image->x_resolution;
1038
+ }
1039
+ }
1040
+
1041
+ if (info->depth != 0)
1042
+ {
1043
+ image->depth = info->depth;
1044
+ }
1045
+
1046
+ option = GetImageOption(info, "dispose");
1047
+ if (option)
1048
+ {
1049
+ image->dispose = rm_dispose_to_enum(option);
1050
+ }
1051
+
1052
+ if (info->extract)
1053
+ {
1054
+ ParseAbsoluteGeometry(info->extract, &image->extract_info);
1055
+ }
1056
+
1057
+ if (info->fuzz != 0.0)
1058
+ {
1059
+ image->fuzz = info->fuzz;
1060
+ }
1061
+
1062
+ option = GetImageOption(info, "gravity");
1063
+ if (option)
1064
+ {
1065
+ image->gravity = rm_gravity_to_enum(option);
1066
+ }
1067
+
1068
+ if (info->interlace != NoInterlace)
1069
+ {
1070
+ image->interlace = info->interlace;
1071
+ }
1072
+
1073
+ option = GetImageOption(info,"mattecolor");
1074
+ if (option)
1075
+ {
1076
+ image->matte_color = info->matte_color;
1077
+ }
1078
+
1079
+ if (info->orientation != UndefinedOrientation)
1080
+ {
1081
+ image->orientation = info->orientation;
1082
+ }
1083
+
1084
+ if (info->page)
1085
+ {
1086
+ (void)ParseAbsoluteGeometry(info->page, &image->page);
1087
+ }
1088
+
1089
+ if (info->quality != 0UL)
1090
+ {
1091
+ image->quality = info->quality;
1092
+ }
1093
+
1094
+ option = GetImageOption(info, "scene");
1095
+ if (option)
1096
+ {
1097
+ image->scene = info->scene;
1098
+ }
1099
+
1100
+ option = GetImageOption(info, "tile-offset");
1101
+ if (option)
1102
+ {
1103
+ (void)ParseAbsoluteGeometry(option, &image->tile_offset);
1104
+ }
1105
+
1106
+ option = GetImageOption(info, "transparent");
1107
+ if (option)
1108
+ {
1109
+ image->transparent_color = info->transparent_color;
1110
+ }
1111
+
1112
+ #if defined(HAVE_ST_TYPE)
1113
+ if (info->type != UndefinedType)
1114
+ {
1115
+ image->type = info->type;
1116
+ }
1117
+ #endif
1118
+
1119
+ if (info->units != UndefinedResolution)
1120
+ {
1121
+ if (image->units != info->units)
1122
+ {
1123
+ switch (image->units)
1124
+ {
1125
+ case PixelsPerInchResolution:
1126
+ {
1127
+ if (info->units == PixelsPerCentimeterResolution)
1128
+ {
1129
+ image->x_resolution /= 2.54;
1130
+ image->y_resolution /= 2.54;
1131
+ }
1132
+ break;
1133
+ }
1134
+ case PixelsPerCentimeterResolution:
1135
+ {
1136
+ if (info->units == PixelsPerInchResolution)
1137
+ {
1138
+ image->x_resolution *= 2.54;
1139
+ image->y_resolution *= 2.54;
1140
+ }
1141
+ break;
1142
+ }
1143
+ default:
1144
+ break;
1145
+ }
1146
+ }
1147
+
1148
+ image->units = info->units;
1149
+ }
1150
+
1151
+ #if defined(HAVE_SETIMAGEARTIFACT)
1152
+ copy_options(image, info);
1153
+ #endif
1154
+ }
1155
+
1156
+
1157
+ /**
1158
+ * Replicate old (ImageMagick < 6.3.2) EXIF:* functionality using
1159
+ * GetImageProperty by returning the exif entries as a single string, separated
1160
+ * by \n's. Do this so that RMagick.rb works no matter which version of
1161
+ * ImageMagick is in use.
1162
+ *
1163
+ * No Ruby usage (internal function)
1164
+ *
1165
+ * @param image the image
1166
+ * @return string representation of exif properties
1167
+ * @see magick/identify.c in ImageMagick
1168
+ */
1169
+ VALUE
1170
+ rm_exif_by_entry(Image *image)
1171
+ {
1172
+ const char *property, *value;
1173
+ char *str;
1174
+ size_t len = 0, property_l, value_l;
1175
+ VALUE v;
1176
+
1177
+ (void) GetImageProperty(image, "exif:*");
1178
+ ResetImagePropertyIterator(image);
1179
+ property = GetNextImageProperty(image);
1180
+
1181
+ // Measure the exif properties and values
1182
+ while (property)
1183
+ {
1184
+ // ignore properties that don't start with "exif:"
1185
+ property_l = strlen(property);
1186
+ if (property_l > 5 && rm_strncasecmp(property, "exif:", 5) == 0)
1187
+ {
1188
+ if (len > 0)
1189
+ {
1190
+ len += 1; // there will be a \n between property=value entries
1191
+ }
1192
+ len += property_l - 5;
1193
+ value = GetImageProperty(image,property);
1194
+ if (value)
1195
+ {
1196
+ // add 1 for the = between property and value
1197
+ len += 1 + strlen(value);
1198
+ }
1199
+ }
1200
+ property = GetNextImageProperty(image);
1201
+ }
1202
+
1203
+ if (len == 0)
1204
+ {
1205
+ return Qnil;
1206
+ }
1207
+ str = xmalloc(len);
1208
+ len = 0;
1209
+
1210
+ // Copy the exif properties and values into the string.
1211
+ ResetImagePropertyIterator(image);
1212
+ property = GetNextImageProperty(image);
1213
+
1214
+ while (property)
1215
+ {
1216
+ property_l = strlen(property);
1217
+ if (property_l > 5 && rm_strncasecmp(property, "exif:", 5) == 0)
1218
+ {
1219
+ if (len > 0)
1220
+ {
1221
+ str[len++] = '\n';
1222
+ }
1223
+ memcpy(str+len, property+5, property_l-5);
1224
+ len += property_l - 5;
1225
+ value = GetImageProperty(image,property);
1226
+ if (value)
1227
+ {
1228
+ value_l = strlen(value);
1229
+ str[len++] = '=';
1230
+ memcpy(str+len, value, value_l);
1231
+ len += value_l;
1232
+ }
1233
+ }
1234
+ property = GetNextImageProperty(image);
1235
+ }
1236
+
1237
+ v = rb_str_new(str, len);
1238
+ xfree(str);
1239
+
1240
+ RB_GC_GUARD(v);
1241
+
1242
+ return v;
1243
+ }
1244
+
1245
+
1246
+ /**
1247
+ * Replicate old (ImageMagick < 6.3.2) EXIF:! functionality using
1248
+ * GetImageProperty by returning the exif entries as a single string, separated
1249
+ * by \n's. Do this so that RMagick.rb works no matter which version of
1250
+ * ImageMagick is in use.
1251
+ *
1252
+ * No Ruby usage (internal function)
1253
+ *
1254
+ * @param image the image
1255
+ * @return string representation of exif properties
1256
+ * @see magick/identify.c in ImageMagick
1257
+ */
1258
+ VALUE
1259
+ rm_exif_by_number(Image *image)
1260
+ {
1261
+ const char *property, *value;
1262
+ char *str;
1263
+ size_t len = 0, property_l, value_l;
1264
+ VALUE v;
1265
+
1266
+ (void) GetImageProperty(image, "exif:!");
1267
+ ResetImagePropertyIterator(image);
1268
+ property = GetNextImageProperty(image);
1269
+
1270
+ // Measure the exif properties and values
1271
+ while (property)
1272
+ {
1273
+ // ignore properties that don't start with "#"
1274
+ property_l = strlen(property);
1275
+ if (property_l > 1 && property[0] == '#')
1276
+ {
1277
+ if (len > 0)
1278
+ {
1279
+ len += 1; // there will be a \n between property=value entries
1280
+ }
1281
+ len += property_l;
1282
+ value = GetImageProperty(image,property);
1283
+ if (value)
1284
+ {
1285
+ // add 1 for the = between property and value
1286
+ len += 1 + strlen(value);
1287
+ }
1288
+ }
1289
+ property = GetNextImageProperty(image);
1290
+ }
1291
+
1292
+ if (len == 0)
1293
+ {
1294
+ return Qnil;
1295
+ }
1296
+ str = xmalloc(len);
1297
+ len = 0;
1298
+
1299
+ // Copy the exif properties and values into the string.
1300
+ ResetImagePropertyIterator(image);
1301
+ property = GetNextImageProperty(image);
1302
+
1303
+ while (property)
1304
+ {
1305
+ property_l = strlen(property);
1306
+ if (property_l > 1 && property[0] == '#')
1307
+ {
1308
+ if (len > 0)
1309
+ {
1310
+ str[len++] = '\n';
1311
+ }
1312
+ memcpy(str+len, property, property_l);
1313
+ len += property_l;
1314
+ value = GetImageProperty(image,property);
1315
+ if (value)
1316
+ {
1317
+ value_l = strlen(value);
1318
+ str[len++] = '=';
1319
+ memcpy(str+len, value, value_l);
1320
+ len += value_l;
1321
+ }
1322
+ }
1323
+ property = GetNextImageProperty(image);
1324
+ }
1325
+
1326
+ v = rb_str_new(str, len);
1327
+ xfree(str);
1328
+
1329
+ RB_GC_GUARD(v);
1330
+
1331
+ return v;
1332
+ }
1333
+
1334
+
1335
+ /**
1336
+ * Get the values from a Geometry object and return them in C variables.
1337
+ *
1338
+ * No Ruby usage (internal function)
1339
+ *
1340
+ * Notes:
1341
+ * - No return value: modifies x, y, width, height, and flag
1342
+ *
1343
+ * @param geom the Geometry object
1344
+ * @param x pointer to the x position of the start of the rectangle
1345
+ * @param y pointer to the y position of the start of the rectangle
1346
+ * @param width pointer to the width of the rectangle
1347
+ * @param height pointer to the height of the rectangle
1348
+ * @param flag pointer to the Geometry's flag
1349
+ */
1350
+ void
1351
+ rm_get_geometry(
1352
+ VALUE geom,
1353
+ long *x,
1354
+ long *y,
1355
+ unsigned long *width,
1356
+ unsigned long *height,
1357
+ int *flag)
1358
+ {
1359
+ VALUE v;
1360
+
1361
+ v = rb_funcall(geom, rm_ID_x, 0);
1362
+ *x = NUM2LONG(v);
1363
+ v = rb_funcall(geom, rm_ID_y, 0);
1364
+ *y = NUM2LONG(v);
1365
+ v = rb_funcall(geom, rm_ID_width, 0);
1366
+ *width = NUM2ULONG(v);
1367
+ v = rb_funcall(geom, rm_ID_height, 0);
1368
+ *height = NUM2ULONG(v);
1369
+
1370
+ // Getting the flag field is a bit more difficult since it's
1371
+ // supposed to be an instance of the GeometryValue Enum class. We
1372
+ // may not know the VALUE for the GeometryValue class, and we
1373
+ // need to check that the flag field is an instance of that class.
1374
+ if (flag)
1375
+ {
1376
+ MagickEnum *magick_enum;
1377
+
1378
+ v = rb_funcall(geom, rm_ID_flag, 0);
1379
+ if (!Class_GeometryValue)
1380
+ {
1381
+ Class_GeometryValue = rb_const_get(Module_Magick, rm_ID_GeometryValue);
1382
+ }
1383
+ if (CLASS_OF(v) != Class_GeometryValue)
1384
+ {
1385
+ rb_raise(rb_eTypeError, "wrong enumeration type - expected %s, got %s"
1386
+ , rb_class2name(Class_GeometryValue),rb_class2name(CLASS_OF(v)));
1387
+ }
1388
+ Data_Get_Struct(v, MagickEnum, magick_enum);
1389
+ *flag = magick_enum->val;
1390
+ }
1391
+
1392
+ }
1393
+
1394
+
1395
+ /**
1396
+ * Clone an image, handle errors.
1397
+ *
1398
+ * No Ruby usage (internal function)
1399
+ *
1400
+ * Notes:
1401
+ * - Don't trace creation - the clone may not be used as an Image object. Let
1402
+ * the caller do the trace if desired.
1403
+ *
1404
+ * @param image the image to clone
1405
+ * @return the cloned image
1406
+ */
1407
+ Image *
1408
+ rm_clone_image(Image *image)
1409
+ {
1410
+ Image *clone;
1411
+ ExceptionInfo *exception;
1412
+
1413
+ exception = AcquireExceptionInfo();
1414
+ clone = CloneImage(image, 0, 0, MagickTrue, exception);
1415
+ if (!clone)
1416
+ {
1417
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
1418
+ }
1419
+ rm_check_exception(exception, clone, DestroyOnError);
1420
+ (void) DestroyExceptionInfo(exception);
1421
+
1422
+ return clone;
1423
+ }
1424
+
1425
+
1426
+ /**
1427
+ * SetImage(Info)ProgressMonitor exit.
1428
+ *
1429
+ * No Ruby usage (internal function)
1430
+ *
1431
+ * Notes:
1432
+ * - ImageMagick's "tag" argument is unused. We pass along the method name
1433
+ * instead.
1434
+ *
1435
+ * @param tag ImageMagick argument (unused)
1436
+ * @param of the offset type
1437
+ * @param sp the size type
1438
+ * @param client_data pointer to the progress method to call
1439
+ * @return true if calling client_data returns a non-nil value, otherwise false
1440
+ */
1441
+ MagickBooleanType
1442
+ rm_progress_monitor(
1443
+ const char *tag,
1444
+ const MagickOffsetType of,
1445
+ const MagickSizeType sp,
1446
+ void *client_data)
1447
+ {
1448
+ VALUE rval;
1449
+ VALUE method, offset, span;
1450
+
1451
+ tag = tag; // defeat gcc message
1452
+
1453
+ #if defined(HAVE_LONG_LONG) // defined in Ruby's defines.h
1454
+ offset = rb_ll2inum(of);
1455
+ span = rb_ull2inum(sp);
1456
+ #else
1457
+ offset = rb_int2big((long)of);
1458
+ span = rb_uint2big((unsigned long)sp);
1459
+ #endif
1460
+
1461
+ method = rb_str_new2(rb_id2name(THIS_FUNC()));
1462
+
1463
+ rval = rb_funcall((VALUE)client_data, rm_ID_call, 3, method, offset, span);
1464
+
1465
+ RB_GC_GUARD(rval);
1466
+ RB_GC_GUARD(method);
1467
+ RB_GC_GUARD(offset);
1468
+ RB_GC_GUARD(span);
1469
+
1470
+ return RTEST(rval) ? MagickTrue : MagickFalse;
1471
+ }
1472
+
1473
+
1474
+ /**
1475
+ * Remove the ImageMagick links between images in an scene sequence.
1476
+ *
1477
+ * No Ruby usage (internal function)
1478
+ *
1479
+ * Notes:
1480
+ * - The images remain grouped via the ImageList
1481
+ *
1482
+ * @param image the image
1483
+ */
1484
+ void
1485
+ rm_split(Image *image)
1486
+ {
1487
+
1488
+ if (!image)
1489
+ {
1490
+ rb_bug("RMagick FATAL: split called with NULL argument.");
1491
+ }
1492
+ while (image)
1493
+ {
1494
+ (void) RemoveFirstImageFromList(&image);
1495
+ }
1496
+ }
1497
+
1498
+
1499
+ /**
1500
+ * If an ExceptionInfo struct in a list of images indicates a warning, issue a
1501
+ * warning message. If an ExceptionInfo struct indicates an error, raise an
1502
+ * exception and optionally destroy the images.
1503
+ *
1504
+ * No Ruby usage (internal function)
1505
+ *
1506
+ * @param imglist the list of images
1507
+ * @param retention retention strategy in case of an error (either RetainOnError
1508
+ * or DestroyOnError)
1509
+ */
1510
+ void
1511
+ rm_check_image_exception(Image *imglist, ErrorRetention retention)
1512
+ {
1513
+ ExceptionInfo *exception;
1514
+ Image *badboy = NULL;
1515
+ Image *image;
1516
+
1517
+ if (imglist == NULL)
1518
+ {
1519
+ return;
1520
+ }
1521
+
1522
+ exception = AcquireExceptionInfo();
1523
+
1524
+ // Find the image with the highest severity
1525
+ image = GetFirstImageInList(imglist);
1526
+ while (image)
1527
+ {
1528
+ if (image->exception.severity != UndefinedException)
1529
+ {
1530
+ if (!badboy || image->exception.severity > badboy->exception.severity)
1531
+ {
1532
+ badboy = image;
1533
+ InheritException(exception, &badboy->exception);
1534
+ }
1535
+
1536
+ ClearMagickException(&image->exception);
1537
+ }
1538
+ image = GetNextImageInList(image);
1539
+ }
1540
+
1541
+ if (badboy)
1542
+ {
1543
+ rm_check_exception(exception, imglist, retention);
1544
+ }
1545
+
1546
+ (void) DestroyExceptionInfo(exception);
1547
+ }
1548
+
1549
+
1550
+ /**
1551
+ * Call handle_exception if there is an exception to handle.
1552
+ *
1553
+ * No Ruby usage (internal function)
1554
+ *
1555
+ * @param exception information about the exception
1556
+ * @param imglist the images that caused the exception
1557
+ * @param retention retention strategy in case of an error (either RetainOnError
1558
+ * or DestroyOnError)
1559
+ */
1560
+ void
1561
+ rm_check_exception(ExceptionInfo *exception, Image *imglist, ErrorRetention retention)
1562
+ {
1563
+ if (exception->severity == UndefinedException)
1564
+ {
1565
+ return;
1566
+ }
1567
+
1568
+ handle_exception(exception, imglist, retention);
1569
+ }
1570
+
1571
+
1572
+
1573
+ /**
1574
+ * Called from ImageMagick for a warning.
1575
+ *
1576
+ * No Ruby usage (internal function)
1577
+ *
1578
+ * @param severity information about the severity of the warning (ignored)
1579
+ * @param reason the reason for the warning
1580
+ * @param description description of the warning
1581
+ */
1582
+ void
1583
+ rm_warning_handler(const ExceptionType severity, const char *reason, const char *description)
1584
+ {
1585
+ ExceptionType dummy;
1586
+
1587
+ rb_warning("RMagick: %s: `%s'", reason, description);
1588
+ dummy = severity;
1589
+ dummy = dummy;
1590
+ }
1591
+
1592
+
1593
+ /**
1594
+ * Called from ImageMagick for a error.
1595
+ *
1596
+ * No Ruby usage (internal function)
1597
+ *
1598
+ * @param severity information about the severity of the error (ignored)
1599
+ * @param reason the reason for the error
1600
+ * @param description description of the error
1601
+ */
1602
+ void
1603
+ rm_error_handler(const ExceptionType severity, const char *reason, const char *description)
1604
+ {
1605
+ char msg[500];
1606
+ int len;
1607
+ ExceptionType dummy;
1608
+
1609
+ memset(msg, 0, sizeof(msg));
1610
+ #if defined(HAVE_SNPRINTF)
1611
+ len = snprintf(msg, sizeof(msg), "%s: `%s'", reason, description);
1612
+ #else
1613
+ len = sprintf(msg, "%.250s: `%.240s'", reason, description);
1614
+ #endif
1615
+ msg[len] = '\0';
1616
+
1617
+ rm_magick_error(msg, NULL);
1618
+ dummy = severity;
1619
+ dummy = dummy;
1620
+ }
1621
+
1622
+
1623
+ /**
1624
+ * Called from ImageMagick for a fatal error.
1625
+ *
1626
+ * No Ruby usage (internal function)
1627
+ *
1628
+ * @param severity information about the severity of the error
1629
+ * @param reason the reason for the error
1630
+ * @param description description of the error (ignored)
1631
+ * @throw FatalImageMagickError
1632
+ */
1633
+ void
1634
+ rm_fatal_error_handler(const ExceptionType severity, const char *reason, const char *description)
1635
+ {
1636
+ rb_raise(Class_FatalImageMagickError, "%s", GetLocaleExceptionMessage(severity, reason));
1637
+ description = description;
1638
+ }
1639
+
1640
+
1641
+ /**
1642
+ * Called when rm_check_exception determines that we need to either issue a
1643
+ * warning message or raise an exception. This function allocates a bunch of
1644
+ * stack so we don't call it unless we have to.
1645
+ *
1646
+ * No Ruby usage (internal function)
1647
+ *
1648
+ * @param exception information about the exception
1649
+ * @param imglist the images that caused the exception
1650
+ * @param retention retention strategy in case of an error (either RetainOnError
1651
+ * or DestroyOnError)
1652
+ */
1653
+ static void
1654
+ handle_exception(ExceptionInfo *exception, Image *imglist, ErrorRetention retention)
1655
+ {
1656
+
1657
+ char reason[500];
1658
+ char desc[500];
1659
+ char msg[sizeof(reason)+sizeof(desc)+20];
1660
+
1661
+ memset(msg, 0, sizeof(msg));
1662
+
1663
+
1664
+ // Handle simple warning
1665
+ if (exception->severity < ErrorException)
1666
+ {
1667
+ #if defined(HAVE_SNPRINTF)
1668
+ snprintf(msg, sizeof(msg)-1, "RMagick: %s%s%s",
1669
+ #else
1670
+ sprintf(msg, "RMagick: %.500s%s%.500s",
1671
+ #endif
1672
+ GetLocaleExceptionMessage(exception->severity, exception->reason),
1673
+ exception->description ? ": " : "",
1674
+ exception->description ? GetLocaleExceptionMessage(exception->severity, exception->description) : "");
1675
+ msg[sizeof(msg)-1] = '\0';
1676
+ rb_warning("%s", msg);
1677
+
1678
+ // Caller deletes ExceptionInfo...
1679
+
1680
+ return;
1681
+ }
1682
+
1683
+ // Raise an exception. We're not coming back...
1684
+
1685
+
1686
+ // Newly-created images should be destroyed, images that are part
1687
+ // of image objects should be retained but split.
1688
+ if (imglist)
1689
+ {
1690
+ if (retention == DestroyOnError)
1691
+ {
1692
+ (void) DestroyImageList(imglist);
1693
+ imglist = NULL;
1694
+ }
1695
+ else
1696
+ {
1697
+ rm_split(imglist);
1698
+ }
1699
+ }
1700
+
1701
+
1702
+ // Clone the ExceptionInfo with all arguments on the stack.
1703
+ memset(reason, 0, sizeof(reason));
1704
+ memset(desc, 0, sizeof(desc));
1705
+
1706
+ if (exception->reason)
1707
+ {
1708
+ strncpy(reason, exception->reason, sizeof(reason)-1);
1709
+ reason[sizeof(reason)-1] = '\0';
1710
+ }
1711
+ if (exception->description)
1712
+ {
1713
+ strncpy(desc, exception->description, sizeof(desc)-1);
1714
+ desc[sizeof(desc)-1] = '\0';
1715
+ }
1716
+
1717
+
1718
+ #if defined(HAVE_SNPRINTF)
1719
+ snprintf(msg, sizeof(msg)-1, "%s%s%s",
1720
+ GetLocaleExceptionMessage(exception->severity, reason),
1721
+ desc[0] ? ": " : "",
1722
+ desc[0] ? GetLocaleExceptionMessage(exception->severity, desc) : "");
1723
+ #else
1724
+ sprintf(msg, "%.*s%s%.*s",
1725
+ sizeof(reason)-1, GetLocaleExceptionMessage(exception->severity, reason),
1726
+ desc[0] ? ": " : "",
1727
+ sizeof(desc)-1, desc[0] ? GetLocaleExceptionMessage(exception->severity, desc) : "");
1728
+ #endif
1729
+
1730
+ msg[sizeof(msg)-1] = '\0';
1731
+
1732
+ (void) DestroyExceptionInfo(exception);
1733
+ rm_magick_error(msg, NULL);
1734
+
1735
+ }
1736
+
1737
+
1738
+ /**
1739
+ * RMagick expected a result. If it got NULL instead raise an exception.
1740
+ *
1741
+ * No Ruby usage (internal function)
1742
+ *
1743
+ * @param image the expected result
1744
+ * @throw RuntimeError
1745
+ */
1746
+ void
1747
+ rm_ensure_result(Image *image)
1748
+ {
1749
+ if (!image)
1750
+ {
1751
+ rb_raise(rb_eRuntimeError, MagickPackageName " library function failed to return a result.");
1752
+ }
1753
+ }
1754
+