rmagick 2.16.0 → 5.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (441) hide show
  1. checksums.yaml +5 -5
  2. data/.devcontainer/Dockerfile +14 -0
  3. data/.devcontainer/ImageMagick6/devcontainer.json +11 -0
  4. data/.devcontainer/devcontainer.json +11 -0
  5. data/.devcontainer/setup-repo.sh +10 -0
  6. data/.devcontainer/setup-user.sh +45 -0
  7. data/.editorconfig +3 -0
  8. data/.github/ISSUE_TEMPLATE.md +17 -0
  9. data/.github/workflows/ci.yml +157 -0
  10. data/.gitignore +9 -1
  11. data/.rspec +1 -0
  12. data/.rubocop.yml +37 -340
  13. data/.rubocop_todo.yml +456 -0
  14. data/.yardopts +5 -0
  15. data/CHANGELOG.md +536 -0
  16. data/CODE_OF_CONDUCT.md +122 -7
  17. data/CONTRIBUTING.md +37 -6
  18. data/Gemfile +18 -4
  19. data/README.md +319 -0
  20. data/Rakefile +83 -98
  21. data/before_install_linux.sh +65 -28
  22. data/before_install_osx.sh +58 -2
  23. data/ext/RMagick/extconf.rb +310 -393
  24. data/ext/RMagick/{rmagick.c → rmagick.cpp} +119 -127
  25. data/ext/RMagick/rmagick.h +290 -363
  26. data/ext/RMagick/rmagick_gvl.h +224 -0
  27. data/ext/RMagick/rmdraw.cpp +1696 -0
  28. data/ext/RMagick/rmenum.cpp +796 -0
  29. data/ext/RMagick/{rmfill.c → rmfill.cpp} +287 -197
  30. data/ext/RMagick/rmilist.cpp +1275 -0
  31. data/ext/RMagick/rmimage.cpp +16459 -0
  32. data/ext/RMagick/{rminfo.c → rminfo.cpp} +738 -910
  33. data/ext/RMagick/rmkinfo.cpp +210 -0
  34. data/ext/RMagick/rmmain.cpp +1923 -0
  35. data/ext/RMagick/rmmontage.cpp +474 -0
  36. data/ext/RMagick/rmpixel.cpp +1322 -0
  37. data/ext/RMagick/{rmstruct.c → rmstruct.cpp} +104 -284
  38. data/ext/RMagick/{rmutil.c → rmutil.cpp} +500 -433
  39. data/lib/rmagick/version.rb +5 -4
  40. data/lib/rmagick.rb +2 -0
  41. data/lib/rmagick_internal.rb +397 -459
  42. data/lib/rvg/clippath.rb +3 -4
  43. data/lib/rvg/container.rb +30 -22
  44. data/lib/rvg/deep_equal.rb +11 -11
  45. data/lib/rvg/describable.rb +2 -2
  46. data/lib/rvg/embellishable.rb +67 -68
  47. data/lib/rvg/misc.rb +139 -142
  48. data/lib/rvg/paint.rb +2 -1
  49. data/lib/rvg/pathdata.rb +7 -8
  50. data/lib/rvg/rvg.rb +49 -46
  51. data/lib/rvg/stretchable.rb +22 -28
  52. data/lib/rvg/stylable.rb +12 -10
  53. data/lib/rvg/text.rb +169 -165
  54. data/lib/rvg/transformable.rb +17 -16
  55. data/lib/rvg/units.rb +5 -5
  56. data/rmagick.gemspec +7 -41
  57. data/sig/rmagick/_draw_common_methods.rbs +64 -0
  58. data/sig/rmagick/_image_common_methods.rbs +389 -0
  59. data/sig/rmagick/draw.rbs +38 -0
  60. data/sig/rmagick/draw_attribute.rbs +28 -0
  61. data/sig/rmagick/enum.rbs +814 -0
  62. data/sig/rmagick/error.rbs +11 -0
  63. data/sig/rmagick/fill.rbs +21 -0
  64. data/sig/rmagick/geometry.rbs +14 -0
  65. data/sig/rmagick/image.rbs +194 -0
  66. data/sig/rmagick/image_list.rbs +181 -0
  67. data/sig/rmagick/iptc.rbs +101 -0
  68. data/sig/rmagick/kernel_info.rbs +12 -0
  69. data/sig/rmagick/optional_method_arguments.rbs +10 -0
  70. data/sig/rmagick/pixel.rbs +46 -0
  71. data/sig/rmagick/struct.rbs +90 -0
  72. data/sig/rmagick.rbs +43 -0
  73. data/sig/rvg/clippath.rbs +34 -0
  74. data/sig/rvg/container.rbs +78 -0
  75. data/sig/rvg/deep_equal.rbs +48 -0
  76. data/sig/rvg/describable.rbs +30 -0
  77. data/sig/rvg/embellishable.rbs +226 -0
  78. data/sig/rvg/misc.rbs +145 -0
  79. data/sig/rvg/paint.rbs +55 -0
  80. data/sig/rvg/pathdata.rbs +77 -0
  81. data/sig/rvg/rvg.rbs +125 -0
  82. data/sig/rvg/stretchable.rbs +56 -0
  83. data/sig/rvg/stylable.rbs +66 -0
  84. data/sig/rvg/text.rbs +118 -0
  85. data/sig/rvg/transformable.rbs +59 -0
  86. data/sig/rvg/units.rbs +33 -0
  87. metadata +68 -428
  88. data/.hound.yml +0 -2
  89. data/.simplecov +0 -27
  90. data/.travis.yml +0 -74
  91. data/Doxyfile +0 -1514
  92. data/README.textile +0 -251
  93. data/deprecated/RMagick.rb +0 -6
  94. data/doc/.cvsignore +0 -1
  95. data/doc/comtasks.html +0 -287
  96. data/doc/constants.html +0 -1581
  97. data/doc/css/doc.css +0 -299
  98. data/doc/css/popup.css +0 -34
  99. data/doc/css/ref.css +0 -67
  100. data/doc/draw.html +0 -3272
  101. data/doc/ex/InitialCoords.rb +0 -22
  102. data/doc/ex/NewCoordSys.rb +0 -30
  103. data/doc/ex/OrigCoordSys.rb +0 -16
  104. data/doc/ex/PreserveAspectRatio.rb +0 -204
  105. data/doc/ex/RotateScale.rb +0 -36
  106. data/doc/ex/Skew.rb +0 -38
  107. data/doc/ex/Use01.rb +0 -15
  108. data/doc/ex/Use02.rb +0 -20
  109. data/doc/ex/Use03.rb +0 -16
  110. data/doc/ex/ViewBox.rb +0 -31
  111. data/doc/ex/adaptive_threshold.rb +0 -9
  112. data/doc/ex/add_noise.rb +0 -16
  113. data/doc/ex/affine.rb +0 -48
  114. data/doc/ex/affine_transform.rb +0 -20
  115. data/doc/ex/arc.rb +0 -49
  116. data/doc/ex/arcpath.rb +0 -32
  117. data/doc/ex/arcs01.rb +0 -28
  118. data/doc/ex/arcs02.rb +0 -59
  119. data/doc/ex/average.rb +0 -15
  120. data/doc/ex/axes.rb +0 -64
  121. data/doc/ex/baseline_shift01.rb +0 -17
  122. data/doc/ex/bilevel_channel.rb +0 -8
  123. data/doc/ex/blur_image.rb +0 -12
  124. data/doc/ex/border.rb +0 -10
  125. data/doc/ex/bounding_box.rb +0 -42
  126. data/doc/ex/cbezier1.rb +0 -41
  127. data/doc/ex/cbezier2.rb +0 -41
  128. data/doc/ex/cbezier3.rb +0 -41
  129. data/doc/ex/cbezier4.rb +0 -42
  130. data/doc/ex/cbezier5.rb +0 -42
  131. data/doc/ex/cbezier6.rb +0 -53
  132. data/doc/ex/channel.rb +0 -25
  133. data/doc/ex/charcoal.rb +0 -12
  134. data/doc/ex/chop.rb +0 -29
  135. data/doc/ex/circle.rb +0 -33
  136. data/doc/ex/circle01.rb +0 -16
  137. data/doc/ex/clip_path.rb +0 -60
  138. data/doc/ex/coalesce.rb +0 -57
  139. data/doc/ex/color_fill_to_border.rb +0 -29
  140. data/doc/ex/color_floodfill.rb +0 -28
  141. data/doc/ex/color_histogram.rb +0 -47
  142. data/doc/ex/color_reset.rb +0 -11
  143. data/doc/ex/colorize.rb +0 -16
  144. data/doc/ex/colors.rb +0 -64
  145. data/doc/ex/compose_mask.rb +0 -22
  146. data/doc/ex/composite.rb +0 -133
  147. data/doc/ex/composite_layers.rb +0 -53
  148. data/doc/ex/composite_tiled.rb +0 -21
  149. data/doc/ex/contrast.rb +0 -36
  150. data/doc/ex/crop.rb +0 -31
  151. data/doc/ex/crop_with_gravity.rb +0 -42
  152. data/doc/ex/cubic01.rb +0 -43
  153. data/doc/ex/cubic02.rb +0 -91
  154. data/doc/ex/cycle_colormap.rb +0 -21
  155. data/doc/ex/dissolve.rb +0 -12
  156. data/doc/ex/drawcomp.rb +0 -42
  157. data/doc/ex/drop_shadow.rb +0 -60
  158. data/doc/ex/edge.rb +0 -11
  159. data/doc/ex/ellipse.rb +0 -45
  160. data/doc/ex/ellipse01.rb +0 -21
  161. data/doc/ex/emboss.rb +0 -11
  162. data/doc/ex/enhance.rb +0 -28
  163. data/doc/ex/equalize.rb +0 -11
  164. data/doc/ex/evenodd.rb +0 -42
  165. data/doc/ex/fill_pattern.rb +0 -23
  166. data/doc/ex/flatten_images.rb +0 -36
  167. data/doc/ex/flip.rb +0 -11
  168. data/doc/ex/flop.rb +0 -11
  169. data/doc/ex/font_styles.rb +0 -32
  170. data/doc/ex/fonts.rb +0 -20
  171. data/doc/ex/frame.rb +0 -12
  172. data/doc/ex/gaussian_blur.rb +0 -11
  173. data/doc/ex/get_multiline_type_metrics.rb +0 -41
  174. data/doc/ex/get_pixels.rb +0 -47
  175. data/doc/ex/get_type_metrics.rb +0 -141
  176. data/doc/ex/gradientfill.rb +0 -27
  177. data/doc/ex/grav.rb +0 -45
  178. data/doc/ex/gravity.rb +0 -80
  179. data/doc/ex/group.rb +0 -26
  180. data/doc/ex/hatchfill.rb +0 -27
  181. data/doc/ex/image.rb +0 -44
  182. data/doc/ex/images/Apple.miff +0 -0
  183. data/doc/ex/images/Ballerina.jpg +0 -0
  184. data/doc/ex/images/Ballerina3.jpg +0 -0
  185. data/doc/ex/images/Button_0.gif +0 -0
  186. data/doc/ex/images/Button_1.gif +0 -0
  187. data/doc/ex/images/Button_2.gif +0 -0
  188. data/doc/ex/images/Button_3.gif +0 -0
  189. data/doc/ex/images/Button_4.gif +0 -0
  190. data/doc/ex/images/Button_5.gif +0 -0
  191. data/doc/ex/images/Button_6.gif +0 -0
  192. data/doc/ex/images/Button_7.gif +0 -0
  193. data/doc/ex/images/Button_8.gif +0 -0
  194. data/doc/ex/images/Button_9.gif +0 -0
  195. data/doc/ex/images/Button_A.gif +0 -0
  196. data/doc/ex/images/Button_B.gif +0 -0
  197. data/doc/ex/images/Button_C.gif +0 -0
  198. data/doc/ex/images/Button_D.gif +0 -0
  199. data/doc/ex/images/Button_E.gif +0 -0
  200. data/doc/ex/images/Button_F.gif +0 -0
  201. data/doc/ex/images/Button_G.gif +0 -0
  202. data/doc/ex/images/Button_H.gif +0 -0
  203. data/doc/ex/images/Button_I.gif +0 -0
  204. data/doc/ex/images/Button_J.gif +0 -0
  205. data/doc/ex/images/Button_K.gif +0 -0
  206. data/doc/ex/images/Button_L.gif +0 -0
  207. data/doc/ex/images/Button_M.gif +0 -0
  208. data/doc/ex/images/Button_N.gif +0 -0
  209. data/doc/ex/images/Button_O.gif +0 -0
  210. data/doc/ex/images/Button_P.gif +0 -0
  211. data/doc/ex/images/Button_Q.gif +0 -0
  212. data/doc/ex/images/Button_R.gif +0 -0
  213. data/doc/ex/images/Button_S.gif +0 -0
  214. data/doc/ex/images/Button_T.gif +0 -0
  215. data/doc/ex/images/Button_U.gif +0 -0
  216. data/doc/ex/images/Button_V.gif +0 -0
  217. data/doc/ex/images/Button_W.gif +0 -0
  218. data/doc/ex/images/Button_X.gif +0 -0
  219. data/doc/ex/images/Button_Y.gif +0 -0
  220. data/doc/ex/images/Button_Z.gif +0 -0
  221. data/doc/ex/images/Cheetah.jpg +0 -0
  222. data/doc/ex/images/Coffee.wmf +0 -0
  223. data/doc/ex/images/Flower_Hat.jpg +0 -0
  224. data/doc/ex/images/Gold_Statue.jpg +0 -0
  225. data/doc/ex/images/Hot_Air_Balloons.jpg +0 -0
  226. data/doc/ex/images/Hot_Air_Balloons_H.jpg +0 -0
  227. data/doc/ex/images/Leaf.miff +0 -0
  228. data/doc/ex/images/No.wmf +0 -0
  229. data/doc/ex/images/Polynesia.jpg +0 -0
  230. data/doc/ex/images/Red_Rocks.jpg +0 -0
  231. data/doc/ex/images/Rocks_On_Beach.miff +0 -0
  232. data/doc/ex/images/Shorts.jpg +0 -0
  233. data/doc/ex/images/Snake.wmf +0 -0
  234. data/doc/ex/images/Violin.jpg +0 -0
  235. data/doc/ex/images/Yellow_Rose.miff +0 -0
  236. data/doc/ex/images/big-duck.gif +0 -0
  237. data/doc/ex/images/duck.gif +0 -0
  238. data/doc/ex/images/duck0.gif +0 -0
  239. data/doc/ex/images/duck1.gif +0 -0
  240. data/doc/ex/images/duck10.gif +0 -0
  241. data/doc/ex/images/duck11.gif +0 -0
  242. data/doc/ex/images/duck12.gif +0 -0
  243. data/doc/ex/images/duck13.gif +0 -0
  244. data/doc/ex/images/duck14.gif +0 -0
  245. data/doc/ex/images/duck15.gif +0 -0
  246. data/doc/ex/images/duck2.gif +0 -0
  247. data/doc/ex/images/duck3.gif +0 -0
  248. data/doc/ex/images/duck4.gif +0 -0
  249. data/doc/ex/images/duck5.gif +0 -0
  250. data/doc/ex/images/duck6.gif +0 -0
  251. data/doc/ex/images/duck7.gif +0 -0
  252. data/doc/ex/images/duck8.gif +0 -0
  253. data/doc/ex/images/duck9.gif +0 -0
  254. data/doc/ex/images/graydient230x6.gif +0 -0
  255. data/doc/ex/images/image_with_profile.jpg +0 -0
  256. data/doc/ex/images/logo400x83.gif +0 -0
  257. data/doc/ex/images/model.miff +0 -0
  258. data/doc/ex/images/notimplemented.gif +0 -0
  259. data/doc/ex/images/smile.miff +0 -0
  260. data/doc/ex/images/spin.gif +0 -0
  261. data/doc/ex/implode.rb +0 -34
  262. data/doc/ex/level.rb +0 -11
  263. data/doc/ex/level_colors.rb +0 -11
  264. data/doc/ex/line.rb +0 -41
  265. data/doc/ex/line01.rb +0 -21
  266. data/doc/ex/mask.rb +0 -35
  267. data/doc/ex/matte_fill_to_border.rb +0 -39
  268. data/doc/ex/matte_floodfill.rb +0 -32
  269. data/doc/ex/matte_replace.rb +0 -39
  270. data/doc/ex/median_filter.rb +0 -28
  271. data/doc/ex/modulate.rb +0 -11
  272. data/doc/ex/mono.rb +0 -23
  273. data/doc/ex/morph.rb +0 -25
  274. data/doc/ex/mosaic.rb +0 -35
  275. data/doc/ex/motion_blur.rb +0 -11
  276. data/doc/ex/negate.rb +0 -11
  277. data/doc/ex/negate_channel.rb +0 -9
  278. data/doc/ex/nested_rvg.rb +0 -21
  279. data/doc/ex/nonzero.rb +0 -42
  280. data/doc/ex/normalize.rb +0 -11
  281. data/doc/ex/oil_paint.rb +0 -11
  282. data/doc/ex/opacity.rb +0 -37
  283. data/doc/ex/ordered_dither.rb +0 -11
  284. data/doc/ex/path.rb +0 -63
  285. data/doc/ex/pattern1.rb +0 -25
  286. data/doc/ex/pattern2.rb +0 -26
  287. data/doc/ex/polaroid.rb +0 -27
  288. data/doc/ex/polygon.rb +0 -23
  289. data/doc/ex/polygon01.rb +0 -21
  290. data/doc/ex/polyline.rb +0 -22
  291. data/doc/ex/polyline01.rb +0 -21
  292. data/doc/ex/posterize.rb +0 -8
  293. data/doc/ex/preview.rb +0 -8
  294. data/doc/ex/qbezierpath.rb +0 -52
  295. data/doc/ex/quad01.rb +0 -34
  296. data/doc/ex/quantize-m.rb +0 -25
  297. data/doc/ex/radial_blur.rb +0 -9
  298. data/doc/ex/raise.rb +0 -8
  299. data/doc/ex/random_threshold_channel.rb +0 -13
  300. data/doc/ex/rect01.rb +0 -14
  301. data/doc/ex/rect02.rb +0 -20
  302. data/doc/ex/rectangle.rb +0 -34
  303. data/doc/ex/reduce_noise.rb +0 -28
  304. data/doc/ex/remap.rb +0 -11
  305. data/doc/ex/remap_images.rb +0 -19
  306. data/doc/ex/resize_to_fill.rb +0 -8
  307. data/doc/ex/resize_to_fit.rb +0 -8
  308. data/doc/ex/roll.rb +0 -9
  309. data/doc/ex/rotate.rb +0 -44
  310. data/doc/ex/rotate_f.rb +0 -14
  311. data/doc/ex/roundrect.rb +0 -33
  312. data/doc/ex/rubyname.rb +0 -30
  313. data/doc/ex/rvg_clippath.rb +0 -12
  314. data/doc/ex/rvg_linecap.rb +0 -42
  315. data/doc/ex/rvg_linejoin.rb +0 -40
  316. data/doc/ex/rvg_opacity.rb +0 -18
  317. data/doc/ex/rvg_pattern.rb +0 -26
  318. data/doc/ex/rvg_stroke_dasharray.rb +0 -11
  319. data/doc/ex/segment.rb +0 -11
  320. data/doc/ex/sepiatone.rb +0 -7
  321. data/doc/ex/shade.rb +0 -11
  322. data/doc/ex/shadow.rb +0 -30
  323. data/doc/ex/shave.rb +0 -15
  324. data/doc/ex/shear.rb +0 -10
  325. data/doc/ex/sketch.rb +0 -17
  326. data/doc/ex/skewx.rb +0 -51
  327. data/doc/ex/skewy.rb +0 -47
  328. data/doc/ex/smile.rb +0 -125
  329. data/doc/ex/solarize.rb +0 -11
  330. data/doc/ex/sparse_color.rb +0 -54
  331. data/doc/ex/splice.rb +0 -8
  332. data/doc/ex/spread.rb +0 -11
  333. data/doc/ex/stegano.rb +0 -55
  334. data/doc/ex/stroke_dasharray.rb +0 -42
  335. data/doc/ex/stroke_fill.rb +0 -10
  336. data/doc/ex/stroke_linecap.rb +0 -44
  337. data/doc/ex/stroke_linejoin.rb +0 -48
  338. data/doc/ex/stroke_width.rb +0 -49
  339. data/doc/ex/swirl.rb +0 -17
  340. data/doc/ex/text.rb +0 -37
  341. data/doc/ex/text01.rb +0 -16
  342. data/doc/ex/text_align.rb +0 -36
  343. data/doc/ex/text_antialias.rb +0 -37
  344. data/doc/ex/text_styles.rb +0 -19
  345. data/doc/ex/text_undercolor.rb +0 -28
  346. data/doc/ex/texture_fill_to_border.rb +0 -34
  347. data/doc/ex/texture_floodfill.rb +0 -32
  348. data/doc/ex/texturefill.rb +0 -24
  349. data/doc/ex/threshold.rb +0 -13
  350. data/doc/ex/to_blob.rb +0 -13
  351. data/doc/ex/translate.rb +0 -39
  352. data/doc/ex/transparent.rb +0 -38
  353. data/doc/ex/transpose.rb +0 -9
  354. data/doc/ex/transverse.rb +0 -9
  355. data/doc/ex/tref01.rb +0 -24
  356. data/doc/ex/triangle01.rb +0 -15
  357. data/doc/ex/trim.rb +0 -23
  358. data/doc/ex/tspan01.rb +0 -17
  359. data/doc/ex/tspan02.rb +0 -17
  360. data/doc/ex/tspan03.rb +0 -19
  361. data/doc/ex/unsharp_mask.rb +0 -28
  362. data/doc/ex/viewex.rb +0 -33
  363. data/doc/ex/vignette.rb +0 -12
  364. data/doc/ex/watermark.rb +0 -27
  365. data/doc/ex/wave.rb +0 -9
  366. data/doc/ex/wet_floor.rb +0 -58
  367. data/doc/ex/writing_mode01.rb +0 -26
  368. data/doc/ex/writing_mode02.rb +0 -26
  369. data/doc/ilist.html +0 -2056
  370. data/doc/image1.html +0 -4680
  371. data/doc/image2.html +0 -3665
  372. data/doc/image3.html +0 -4522
  373. data/doc/imageattrs.html +0 -1638
  374. data/doc/imusage.html +0 -514
  375. data/doc/index.html +0 -416
  376. data/doc/info.html +0 -1499
  377. data/doc/magick.html +0 -565
  378. data/doc/optequiv.html +0 -2435
  379. data/doc/rvg.html +0 -975
  380. data/doc/rvgclip.html +0 -248
  381. data/doc/rvggroup.html +0 -305
  382. data/doc/rvgimage.html +0 -289
  383. data/doc/rvgpattern.html +0 -475
  384. data/doc/rvgshape.html +0 -406
  385. data/doc/rvgstyle.html +0 -270
  386. data/doc/rvgtext.html +0 -465
  387. data/doc/rvgtspan.html +0 -238
  388. data/doc/rvgtut.html +0 -530
  389. data/doc/rvguse.html +0 -145
  390. data/doc/rvgxform.html +0 -294
  391. data/doc/scripts/doc.js +0 -22
  392. data/doc/scripts/stripeTables.js +0 -23
  393. data/doc/struct.html +0 -1339
  394. data/doc/usage.html +0 -1621
  395. data/examples/constitute.rb +0 -7
  396. data/examples/crop_with_gravity.rb +0 -42
  397. data/examples/demo.rb +0 -324
  398. data/examples/describe.rb +0 -43
  399. data/examples/find_similar_region.rb +0 -34
  400. data/examples/histogram.rb +0 -321
  401. data/examples/identify.rb +0 -185
  402. data/examples/image_opacity.rb +0 -29
  403. data/examples/import_export.rb +0 -31
  404. data/examples/pattern_fill.rb +0 -38
  405. data/examples/rotating_text.rb +0 -44
  406. data/examples/spinner.rb +0 -49
  407. data/examples/thumbnail.rb +0 -64
  408. data/examples/vignette.rb +0 -78
  409. data/ext/RMagick/rmdraw.c +0 -2022
  410. data/ext/RMagick/rmenum.c +0 -1235
  411. data/ext/RMagick/rmilist.c +0 -1270
  412. data/ext/RMagick/rmimage.c +0 -15427
  413. data/ext/RMagick/rmmain.c +0 -1741
  414. data/ext/RMagick/rmmontage.c +0 -519
  415. data/ext/RMagick/rmpixel.c +0 -1114
  416. data/spec/rmagick/ImageList1_spec.rb +0 -24
  417. data/spec/rmagick/draw_spec.rb +0 -156
  418. data/spec/rmagick/image/blue_shift_spec.rb +0 -16
  419. data/spec/rmagick/image/composite_spec.rb +0 -140
  420. data/spec/rmagick/image/constitute_spec.rb +0 -15
  421. data/spec/rmagick/image/dispatch_spec.rb +0 -18
  422. data/spec/rmagick/image/from_blob_spec.rb +0 -14
  423. data/spec/rmagick/image/ping_spec.rb +0 -14
  424. data/spec/rmagick/image/properties_spec.rb +0 -29
  425. data/spec/spec_helper.rb +0 -4
  426. data/test/Image1.rb +0 -565
  427. data/test/Image2.rb +0 -1304
  428. data/test/Image3.rb +0 -1030
  429. data/test/ImageList1.rb +0 -806
  430. data/test/ImageList2.rb +0 -385
  431. data/test/Image_attributes.rb +0 -697
  432. data/test/Import_Export.rb +0 -121
  433. data/test/Info.rb +0 -345
  434. data/test/Magick.rb +0 -321
  435. data/test/Pixel.rb +0 -116
  436. data/test/Preview.rb +0 -57
  437. data/test/cmyk.icm +0 -0
  438. data/test/srgb.icm +0 -0
  439. data/test/test_all_basic.rb +0 -38
  440. data/test/tmpnam_test.rb +0 -50
  441. data/wercker.yml +0 -10
@@ -0,0 +1,1696 @@
1
+ /**************************************************************************//**
2
+ * Contains Draw class methods.
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 rmdraw.cpp
9
+ * @version $Id: rmdraw.cpp,v 1.83 2009/12/20 02:33:33 baror Exp $
10
+ * @author Tim Hunter
11
+ ******************************************************************************/
12
+
13
+ #include "rmagick.h"
14
+ #include "float.h"
15
+
16
+ #ifdef HAVE_RB_GC_MARK_MOVABLE
17
+ static void Draw_compact(void *drawptr);
18
+ #endif
19
+ static void Draw_mark(void *);
20
+ static void Draw_destroy(void *);
21
+ static size_t Draw_memsize(const void *);
22
+ static VALUE new_DrawOptions(void);
23
+ static VALUE get_type_metrics(int, VALUE *, VALUE, gvl_function_t);
24
+
25
+ const rb_data_type_t rm_draw_data_type = {
26
+ "Magick::Draw",
27
+ {
28
+ Draw_mark,
29
+ Draw_destroy,
30
+ Draw_memsize,
31
+ #ifdef HAVE_RB_GC_MARK_MOVABLE
32
+ Draw_compact,
33
+ #endif
34
+ },
35
+ 0, 0,
36
+ RUBY_TYPED_FROZEN_SHAREABLE,
37
+ };
38
+
39
+
40
+ DEFINE_GVL_STUB4(BlobToImage, const ImageInfo *, const void *, const size_t, ExceptionInfo *);
41
+ DEFINE_GVL_STUB4(ImageToBlob, const ImageInfo *, Image *, size_t *, ExceptionInfo *);
42
+ #if defined(IMAGEMAGICK_7)
43
+ DEFINE_GVL_STUB3(AnnotateImage, Image *, const DrawInfo *, ExceptionInfo *);
44
+ DEFINE_GVL_STUB3(DrawImage, Image *, const DrawInfo *, ExceptionInfo *);
45
+ DEFINE_GVL_STUB4(GetMultilineTypeMetrics, Image *, const DrawInfo *, TypeMetric *, ExceptionInfo *);
46
+ DEFINE_GVL_STUB4(GetTypeMetrics, Image *, const DrawInfo *, TypeMetric *, ExceptionInfo *);
47
+ #else
48
+ DEFINE_GVL_STUB2(AnnotateImage, Image *, const DrawInfo *);
49
+ DEFINE_GVL_STUB2(DrawImage, Image *, const DrawInfo *);
50
+ DEFINE_GVL_STUB3(GetMultilineTypeMetrics, Image *, const DrawInfo *, TypeMetric *);
51
+ DEFINE_GVL_STUB3(GetTypeMetrics, Image *, const DrawInfo *, TypeMetric *);
52
+ #endif
53
+
54
+
55
+ /**
56
+ * Set the affine matrix from an {Magick::AffineMatrix}.
57
+ *
58
+ * @param matrix [Magick::AffineMatrix] the affine matrix
59
+ * @return [Magick::AffineMatrix] the given matrix
60
+ */
61
+ VALUE
62
+ Draw_affine_eq(VALUE self, VALUE matrix)
63
+ {
64
+ Draw *draw;
65
+
66
+ rb_check_frozen(self);
67
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
68
+ Export_AffineMatrix(&draw->info->affine, matrix);
69
+ return matrix;
70
+ }
71
+
72
+
73
+ /**
74
+ * Set the text alignment from an {Magick::AlignType}.
75
+ *
76
+ * @param align [Magick::AlignType] the text alignment
77
+ * @return [Magick::AlignType] the given align
78
+ */
79
+ VALUE
80
+ Draw_align_eq(VALUE self, VALUE align)
81
+ {
82
+ Draw *draw;
83
+
84
+ rb_check_frozen(self);
85
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
86
+ VALUE_TO_ENUM(align, draw->info->align, AlignType);
87
+ return align;
88
+ }
89
+
90
+
91
+ /**
92
+ * Set text decorate from an {Magick::DecorationType}.
93
+ *
94
+ * @param decorate [Magick::DecorationType] the decorate type
95
+ * @return [Magick::DecorationType] the given decorate
96
+ */
97
+ VALUE
98
+ Draw_decorate_eq(VALUE self, VALUE decorate)
99
+ {
100
+ Draw *draw;
101
+
102
+ rb_check_frozen(self);
103
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
104
+ VALUE_TO_ENUM(decorate, draw->info->decorate, DecorationType);
105
+ return decorate;
106
+ }
107
+
108
+
109
+ /**
110
+ * Set density.
111
+ *
112
+ * @param density [String] the density
113
+ * @return [String] the given density
114
+ */
115
+ VALUE
116
+ Draw_density_eq(VALUE self, VALUE density)
117
+ {
118
+ Draw *draw;
119
+
120
+ rb_check_frozen(self);
121
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
122
+ magick_clone_string(&draw->info->density, StringValueCStr(density));
123
+
124
+ return density;
125
+ }
126
+
127
+
128
+ /**
129
+ * Set text encoding.
130
+ *
131
+ * @param encoding [String] the encoding name
132
+ * @return [String] the given encoding name
133
+ */
134
+ VALUE
135
+ Draw_encoding_eq(VALUE self, VALUE encoding)
136
+ {
137
+ Draw *draw;
138
+
139
+ rb_check_frozen(self);
140
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
141
+ magick_clone_string(&draw->info->encoding, StringValueCStr(encoding));
142
+
143
+ return encoding;
144
+ }
145
+
146
+
147
+ /**
148
+ * Set fill color.
149
+ *
150
+ * @param fill [Magick::Pixel, String] the fill color
151
+ * @return [Magick::Pixel, String] the given fill color
152
+ */
153
+ VALUE
154
+ Draw_fill_eq(VALUE self, VALUE fill)
155
+ {
156
+ Draw *draw;
157
+
158
+ rb_check_frozen(self);
159
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
160
+ Color_to_PixelColor(&draw->info->fill, fill);
161
+ return fill;
162
+ }
163
+
164
+
165
+ /**
166
+ * Accept an image as a fill pattern.
167
+ *
168
+ * @param pattern [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an
169
+ * imagelist, uses the current image.
170
+ * @return [Magick::Image] the given pattern image
171
+ * @see #stroke_pattern=
172
+ * @see #tile=
173
+ */
174
+ VALUE
175
+ Draw_fill_pattern_eq(VALUE self, VALUE pattern)
176
+ {
177
+ Draw *draw;
178
+
179
+ rb_check_frozen(self);
180
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
181
+
182
+ if (draw->info->fill_pattern != NULL)
183
+ {
184
+ // Do not trace destruction
185
+ DestroyImage(draw->info->fill_pattern);
186
+ draw->info->fill_pattern = NULL;
187
+ }
188
+
189
+ if (!NIL_P(pattern))
190
+ {
191
+ Image *image;
192
+
193
+ pattern = rm_cur_image(pattern);
194
+ image = rm_check_destroyed(pattern);
195
+ // Do not trace creation
196
+ draw->info->fill_pattern = rm_clone_image(image);
197
+ }
198
+
199
+ return pattern;
200
+ }
201
+
202
+
203
+ /**
204
+ * Set the font name.
205
+ *
206
+ * @param font [String] the font name
207
+ * @return [String] the given font name
208
+ */
209
+ VALUE
210
+ Draw_font_eq(VALUE self, VALUE font)
211
+ {
212
+ Draw *draw;
213
+
214
+ rb_check_frozen(self);
215
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
216
+ magick_clone_string(&draw->info->font, StringValueCStr(font));
217
+
218
+ return font;
219
+ }
220
+
221
+
222
+ /**
223
+ * Set the font family name.
224
+ *
225
+ * @param family [String] the font family name
226
+ * @return [String] the given family name
227
+ */
228
+ VALUE
229
+ Draw_font_family_eq(VALUE self, VALUE family)
230
+ {
231
+ Draw *draw;
232
+
233
+ rb_check_frozen(self);
234
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
235
+ magick_clone_string(&draw->info->family, StringValueCStr(family));
236
+
237
+ return family;
238
+ }
239
+
240
+
241
+ /**
242
+ * Set the stretch as spacing between text characters.
243
+ *
244
+ * @param stretch [Magick::StretchType] the stretch type
245
+ * @return [Magick::StretchType] the given stretch type
246
+ */
247
+ VALUE
248
+ Draw_font_stretch_eq(VALUE self, VALUE stretch)
249
+ {
250
+ Draw *draw;
251
+
252
+ rb_check_frozen(self);
253
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
254
+ VALUE_TO_ENUM(stretch, draw->info->stretch, StretchType);
255
+ return stretch;
256
+ }
257
+
258
+
259
+ /**
260
+ * Set font style.
261
+ *
262
+ * @param style [Magick::StyleType] the font style
263
+ * @return [Magick::StyleType] the given font style
264
+ */
265
+ VALUE
266
+ Draw_font_style_eq(VALUE self, VALUE style)
267
+ {
268
+ Draw *draw;
269
+
270
+ rb_check_frozen(self);
271
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
272
+ VALUE_TO_ENUM(style, draw->info->style, StyleType);
273
+ return style;
274
+ }
275
+
276
+
277
+ /**
278
+ * Set font weight.
279
+ *
280
+ * @param weight [Magick::WeightType, Numeric] the font weight
281
+ * @return [Magick::WeightType, Numeric] the given font weight
282
+ * @note The font weight can be one of the font weight constants or a number between 100 and 900
283
+ */
284
+ VALUE
285
+ Draw_font_weight_eq(VALUE self, VALUE weight)
286
+ {
287
+ Draw *draw;
288
+ size_t w;
289
+
290
+ rb_check_frozen(self);
291
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
292
+
293
+ if (FIXNUM_P(weight))
294
+ {
295
+ w = FIX2INT(weight);
296
+ if (w < 100 || w > 900)
297
+ {
298
+ rb_raise(rb_eArgError, "invalid font weight (%" RMIuSIZE " given)", w);
299
+ }
300
+ draw->info->weight = w;
301
+ }
302
+ else
303
+ {
304
+ VALUE_TO_ENUM(weight, w, WeightType);
305
+ switch (w)
306
+ {
307
+ case AnyWeight:
308
+ draw->info->weight = 0;
309
+ break;
310
+ case NormalWeight:
311
+ draw->info->weight = 400;
312
+ break;
313
+ case BoldWeight:
314
+ draw->info->weight = 700;
315
+ break;
316
+ case BolderWeight:
317
+ if (draw->info->weight <= 800)
318
+ draw->info->weight += 100;
319
+ break;
320
+ case LighterWeight:
321
+ if (draw->info->weight >= 100)
322
+ draw->info->weight -= 100;
323
+ break;
324
+ default:
325
+ rb_raise(rb_eArgError, "unknown font weight");
326
+ break;
327
+ }
328
+ }
329
+
330
+ return weight;
331
+ }
332
+
333
+
334
+ /**
335
+ * Set gravity to draw text.
336
+ * Gravity affects text placement in bounding area according to rules:
337
+ *
338
+ * - +NorthWestGravity+ - text bottom-left corner placed at top-left
339
+ * - +NorthGravity+ - text bottom-center placed at top-center
340
+ * - +NorthEastGravity+ - text bottom-right corner placed at top-right
341
+ * - +WestGravity+ - text left-center placed at left-center
342
+ * - +CenterGravity+ - text center placed at center
343
+ * - +EastGravity+ - text right-center placed at right-center
344
+ * - +SouthWestGravity+ - text top-left placed at bottom-left
345
+ * - +SouthGravity+ - text top-center placed at bottom-center
346
+ * - +SouthEastGravity+ - text top-right placed at bottom-right
347
+ *
348
+ * @param grav [Magick::GravityType] this gravity type
349
+ * @return [Magick::GravityType] the given gravity type
350
+ */
351
+ VALUE
352
+ Draw_gravity_eq(VALUE self, VALUE grav)
353
+ {
354
+ Draw *draw;
355
+
356
+ rb_check_frozen(self);
357
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
358
+ VALUE_TO_ENUM(grav, draw->info->gravity, GravityType);
359
+
360
+ return grav;
361
+ }
362
+
363
+
364
+ /**
365
+ * Set kerning as spacing between two letters.
366
+ *
367
+ * @param kerning [Float] the kerning
368
+ * @return [Float] the given kerning
369
+ */
370
+ VALUE
371
+ Draw_kerning_eq(VALUE self, VALUE kerning)
372
+ {
373
+ Draw *draw;
374
+
375
+ rb_check_frozen(self);
376
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
377
+ draw->info->kerning = NUM2DBL(kerning);
378
+ return kerning;
379
+ }
380
+
381
+
382
+ /**
383
+ * Set spacing between two lines.
384
+ *
385
+ * @param spacing [Float] the spacing
386
+ * @return [Float] the given spacing
387
+ */
388
+ VALUE
389
+ Draw_interline_spacing_eq(VALUE self, VALUE spacing)
390
+ {
391
+ Draw *draw;
392
+
393
+ rb_check_frozen(self);
394
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
395
+ draw->info->interline_spacing = NUM2DBL(spacing);
396
+ return spacing;
397
+ }
398
+
399
+
400
+ /**
401
+ * Set spacing between two words.
402
+ *
403
+ * @param spacing [Float] the spacing
404
+ * @return [Float] the given spacing
405
+ */
406
+ VALUE
407
+ Draw_interword_spacing_eq(VALUE self, VALUE spacing)
408
+ {
409
+ Draw *draw;
410
+
411
+ rb_check_frozen(self);
412
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
413
+ draw->info->interword_spacing = NUM2DBL(spacing);
414
+ return spacing;
415
+ }
416
+
417
+
418
+ /**
419
+ * Convert an image to a blob and the blob to a String.
420
+ *
421
+ * No Ruby usage (internal function)
422
+ *
423
+ * Notes:
424
+ * - Returns Qnil if there is no image
425
+ *
426
+ * @param image the Image to convert
427
+ * @return Ruby string representation of image
428
+ * @see str_to_image
429
+ */
430
+ static VALUE
431
+ image_to_str(Image *image)
432
+ {
433
+ VALUE dimg = Qnil;
434
+
435
+ if (image)
436
+ {
437
+ unsigned char *blob;
438
+ size_t length;
439
+ Info *info;
440
+ ExceptionInfo *exception;
441
+
442
+ info = CloneImageInfo(NULL);
443
+ exception = AcquireExceptionInfo();
444
+ GVL_STRUCT_TYPE(ImageToBlob) args = { info, image, &length, exception };
445
+ blob = (unsigned char *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(ImageToBlob), &args);
446
+ DestroyImageInfo(info);
447
+ CHECK_EXCEPTION();
448
+ DestroyExceptionInfo(exception);
449
+ dimg = rb_str_new((char *)blob, (long)length);
450
+ magick_free((void*)blob);
451
+ }
452
+
453
+ RB_GC_GUARD(dimg);
454
+
455
+ return dimg;
456
+ }
457
+
458
+
459
+ /**
460
+ * Undo the image_to_str, above.
461
+ *
462
+ * No Ruby usage (internal function)
463
+ *
464
+ * Notes:
465
+ * - Returns NULL if the argument is Qnil
466
+ *
467
+ * @param str the Ruby string to convert
468
+ * @return Image represented by str
469
+ * @see image_to_str
470
+ */
471
+ static
472
+ Image *str_to_image(VALUE str)
473
+ {
474
+ Image *image = NULL;
475
+
476
+ if (str != Qnil)
477
+ {
478
+ Info *info;
479
+ ExceptionInfo *exception;
480
+
481
+ info = CloneImageInfo(NULL);
482
+ exception = AcquireExceptionInfo();
483
+ GVL_STRUCT_TYPE(BlobToImage) args = { info, RSTRING_PTR(str), (size_t)RSTRING_LEN(str), exception };
484
+ image = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(BlobToImage), &args);
485
+ DestroyImageInfo(info);
486
+ CHECK_EXCEPTION();
487
+ DestroyExceptionInfo(exception);
488
+ }
489
+
490
+ return image;
491
+ }
492
+
493
+
494
+ /**
495
+ * Dump custom marshal for Draw objects.
496
+ *
497
+ * - Instead of trying to replicate Ruby's support for cross-system
498
+ * marshalling, exploit it. Convert the Draw fields to Ruby objects and
499
+ * store them in a hash. Let Ruby marshal the hash.
500
+ * - Commented out code that dumps/loads fields that are used internally by
501
+ * ImageMagick and shouldn't be marshaled. I left the code as placeholders
502
+ * so I'll know which fields have been deliberately omitted.
503
+ *
504
+ * @return [Hash] the marshalled object
505
+ * @todo Handle gradients when christy gets the new gradient support added (23Dec08)
506
+ */
507
+ VALUE
508
+ Draw_marshal_dump(VALUE self)
509
+ {
510
+ Draw *draw;
511
+ VALUE ddraw;
512
+
513
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
514
+
515
+ // Raise an exception if the Draw has a non-NULL gradient or element_reference field
516
+ if (draw->info->element_reference.type != UndefinedReference
517
+ || draw->info->gradient.type != UndefinedGradient)
518
+ {
519
+ rb_raise(rb_eTypeError, "can't dump gradient definition");
520
+ }
521
+
522
+ ddraw = rb_hash_new();
523
+
524
+ rb_hash_aset(ddraw, CSTR2SYM("affine"), Import_AffineMatrix(&draw->info->affine));
525
+ rb_hash_aset(ddraw, CSTR2SYM("gravity"), INT2FIX(draw->info->gravity));
526
+ rb_hash_aset(ddraw, CSTR2SYM("fill"), Pixel_from_PixelColor(&draw->info->fill));
527
+ rb_hash_aset(ddraw, CSTR2SYM("stroke"), Pixel_from_PixelColor(&draw->info->stroke));
528
+ rb_hash_aset(ddraw, CSTR2SYM("stroke_width"), rb_float_new(draw->info->stroke_width));
529
+ rb_hash_aset(ddraw, CSTR2SYM("fill_pattern"), image_to_str(draw->info->fill_pattern));
530
+ rb_hash_aset(ddraw, CSTR2SYM("stroke_pattern"), image_to_str(draw->info->stroke_pattern));
531
+ rb_hash_aset(ddraw, CSTR2SYM("stroke_antialias"), draw->info->stroke_antialias ? Qtrue : Qfalse);
532
+ rb_hash_aset(ddraw, CSTR2SYM("text_antialias"), draw->info->text_antialias ? Qtrue : Qfalse);
533
+ rb_hash_aset(ddraw, CSTR2SYM("decorate"), INT2FIX(draw->info->decorate));
534
+ rb_hash_aset(ddraw, CSTR2SYM("font"), MAGICK_STRING_TO_OBJ(draw->info->font));
535
+ rb_hash_aset(ddraw, CSTR2SYM("family"), MAGICK_STRING_TO_OBJ(draw->info->family));
536
+ rb_hash_aset(ddraw, CSTR2SYM("style"), INT2FIX(draw->info->style));
537
+ rb_hash_aset(ddraw, CSTR2SYM("stretch"), INT2FIX(draw->info->stretch));
538
+ rb_hash_aset(ddraw, CSTR2SYM("weight"), ULONG2NUM(draw->info->weight));
539
+ rb_hash_aset(ddraw, CSTR2SYM("encoding"), MAGICK_STRING_TO_OBJ(draw->info->encoding));
540
+ rb_hash_aset(ddraw, CSTR2SYM("pointsize"), rb_float_new(draw->info->pointsize));
541
+ rb_hash_aset(ddraw, CSTR2SYM("density"), MAGICK_STRING_TO_OBJ(draw->info->density));
542
+ rb_hash_aset(ddraw, CSTR2SYM("align"), INT2FIX(draw->info->align));
543
+ rb_hash_aset(ddraw, CSTR2SYM("undercolor"), Pixel_from_PixelColor(&draw->info->undercolor));
544
+ rb_hash_aset(ddraw, CSTR2SYM("clip_units"), INT2FIX(draw->info->clip_units));
545
+ #if defined(IMAGEMAGICK_7)
546
+ rb_hash_aset(ddraw, CSTR2SYM("alpha"), QUANTUM2NUM(draw->info->alpha));
547
+ #else
548
+ rb_hash_aset(ddraw, CSTR2SYM("opacity"), QUANTUM2NUM(draw->info->opacity));
549
+ #endif
550
+ rb_hash_aset(ddraw, CSTR2SYM("kerning"), rb_float_new(draw->info->kerning));
551
+ rb_hash_aset(ddraw, CSTR2SYM("interword_spacing"), rb_float_new(draw->info->interword_spacing));
552
+
553
+ // Non-DrawInfo fields
554
+ rb_hash_aset(ddraw, CSTR2SYM("primitives"), draw->primitives);
555
+
556
+ return ddraw;
557
+ }
558
+
559
+
560
+ /**
561
+ * Load the marshalled object
562
+ *
563
+ * @param ddraw [Hash] the marshalled object
564
+ * @return [Magick::Draw] self, once marshalled
565
+ */
566
+ VALUE
567
+ Draw_marshal_load(VALUE self, VALUE ddraw)
568
+ {
569
+ Draw *draw;
570
+ VALUE val;
571
+
572
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
573
+
574
+ if (draw->info == NULL)
575
+ {
576
+ ImageInfo *image_info;
577
+
578
+ image_info = CloneImageInfo(NULL);
579
+ draw->info = CloneDrawInfo(image_info, (DrawInfo *) NULL);
580
+ DestroyImageInfo(image_info);
581
+ }
582
+ OBJ_TO_MAGICK_STRING(draw->info->geometry, rb_hash_aref(ddraw, CSTR2SYM("geometry")));
583
+
584
+ val = rb_hash_aref(ddraw, CSTR2SYM("affine"));
585
+ Export_AffineMatrix(&draw->info->affine, val);
586
+
587
+ draw->info->gravity = (GravityType) FIX2INT(rb_hash_aref(ddraw, CSTR2SYM("gravity")));
588
+
589
+ val = rb_hash_aref(ddraw, CSTR2SYM("fill"));
590
+ Color_to_PixelColor(&draw->info->fill, val);
591
+
592
+ val = rb_hash_aref(ddraw, CSTR2SYM("stroke"));
593
+ Color_to_PixelColor(&draw->info->stroke, val);
594
+
595
+ draw->info->stroke_width = NUM2DBL(rb_hash_aref(ddraw, CSTR2SYM("stroke_width")));
596
+ draw->info->fill_pattern = str_to_image(rb_hash_aref(ddraw, CSTR2SYM("fill_pattern")));
597
+ draw->info->stroke_pattern = str_to_image(rb_hash_aref(ddraw, CSTR2SYM("stroke_pattern")));
598
+ draw->info->stroke_antialias = (MagickBooleanType)RTEST(rb_hash_aref(ddraw, CSTR2SYM("stroke_antialias")));
599
+ draw->info->text_antialias = (MagickBooleanType)RTEST(rb_hash_aref(ddraw, CSTR2SYM("text_antialias")));
600
+ draw->info->decorate = (DecorationType) FIX2INT(rb_hash_aref(ddraw, CSTR2SYM("decorate")));
601
+ OBJ_TO_MAGICK_STRING(draw->info->font, rb_hash_aref(ddraw, CSTR2SYM("font")));
602
+ OBJ_TO_MAGICK_STRING(draw->info->family, rb_hash_aref(ddraw, CSTR2SYM("family")));
603
+
604
+ draw->info->style = (StyleType) FIX2INT(rb_hash_aref(ddraw, CSTR2SYM("style")));
605
+ draw->info->stretch = (StretchType) FIX2INT(rb_hash_aref(ddraw, CSTR2SYM("stretch")));
606
+ draw->info->weight = NUM2ULONG(rb_hash_aref(ddraw, CSTR2SYM("weight")));
607
+ OBJ_TO_MAGICK_STRING(draw->info->encoding, rb_hash_aref(ddraw, CSTR2SYM("encoding")));
608
+ draw->info->pointsize = NUM2DBL(rb_hash_aref(ddraw, CSTR2SYM("pointsize")));
609
+ OBJ_TO_MAGICK_STRING(draw->info->density, rb_hash_aref(ddraw, CSTR2SYM("density")));
610
+ draw->info->align = (AlignType) FIX2INT(rb_hash_aref(ddraw, CSTR2SYM("align")));
611
+
612
+ val = rb_hash_aref(ddraw, CSTR2SYM("undercolor"));
613
+ Color_to_PixelColor(&draw->info->undercolor, val);
614
+
615
+ draw->info->clip_units = (ClipPathUnits)FIX2INT(rb_hash_aref(ddraw, CSTR2SYM("clip_units")));
616
+ #if defined(IMAGEMAGICK_7)
617
+ draw->info->alpha = NUM2QUANTUM(rb_hash_aref(ddraw, CSTR2SYM("alpha")));
618
+ #else
619
+ draw->info->opacity = NUM2QUANTUM(rb_hash_aref(ddraw, CSTR2SYM("opacity")));
620
+ #endif
621
+ draw->info->kerning = NUM2DBL(rb_hash_aref(ddraw, CSTR2SYM("kerning")));
622
+ draw->info->interword_spacing = NUM2DBL(rb_hash_aref(ddraw, CSTR2SYM("interword_spacing")));
623
+
624
+ draw->primitives = rb_hash_aref(ddraw, CSTR2SYM("primitives"));
625
+
626
+ RB_GC_GUARD(val);
627
+
628
+ return self;
629
+ }
630
+
631
+
632
+ /**
633
+ * Set point size to draw text.
634
+ *
635
+ * @param pointsize [Float] the pointsize
636
+ * @return [Float] the given pointsize
637
+ */
638
+ VALUE
639
+ Draw_pointsize_eq(VALUE self, VALUE pointsize)
640
+ {
641
+ Draw *draw;
642
+
643
+ rb_check_frozen(self);
644
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
645
+ draw->info->pointsize = NUM2DBL(pointsize);
646
+ return pointsize;
647
+ }
648
+
649
+
650
+ /**
651
+ * Set rotation. The argument should be in degrees.
652
+ *
653
+ * @param deg [Float] the number of degrees
654
+ * @return [Float] the given degrees
655
+ */
656
+ VALUE
657
+ Draw_rotation_eq(VALUE self, VALUE deg)
658
+ {
659
+ Draw *draw;
660
+ double degrees;
661
+ AffineMatrix affine, current;
662
+
663
+ rb_check_frozen(self);
664
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
665
+
666
+ degrees = NUM2DBL(deg);
667
+ if (fabs(degrees) > DBL_EPSILON)
668
+ {
669
+ current = draw->info->affine;
670
+ affine.sx = cos(DegreesToRadians(fmod(degrees, 360.0)));
671
+ affine.rx = sin(DegreesToRadians(fmod(degrees, 360.0)));
672
+ affine.tx = 0.0;
673
+ affine.ry = (-sin(DegreesToRadians(fmod(degrees, 360.0))));
674
+ affine.sy = cos(DegreesToRadians(fmod(degrees, 360.0)));
675
+ affine.ty = 0.0;
676
+
677
+ draw->info->affine.sx = current.sx*affine.sx+current.ry*affine.rx;
678
+ draw->info->affine.rx = current.rx*affine.sx+current.sy*affine.rx;
679
+ draw->info->affine.ry = current.sx*affine.ry+current.ry*affine.sy;
680
+ draw->info->affine.sy = current.rx*affine.ry+current.sy*affine.sy;
681
+ draw->info->affine.tx = current.sx*affine.tx+current.ry*affine.ty+current.tx;
682
+ }
683
+
684
+ return deg;
685
+ }
686
+
687
+
688
+ /**
689
+ * Set stroke.
690
+ *
691
+ * @param stroke [Magick::Pixel, String] the stroke
692
+ * @return [Magick::Pixel, String] the given stroke
693
+ */
694
+ VALUE
695
+ Draw_stroke_eq(VALUE self, VALUE stroke)
696
+ {
697
+ Draw *draw;
698
+
699
+ rb_check_frozen(self);
700
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
701
+ Color_to_PixelColor(&draw->info->stroke, stroke);
702
+ return stroke;
703
+ }
704
+
705
+
706
+ /**
707
+ * Accept an image as a stroke pattern.
708
+ *
709
+ * @param pattern [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an
710
+ * imagelist, uses the current image.
711
+ * @return [Magick::Image] the given pattern
712
+ * @see #fill_pattern
713
+ */
714
+ VALUE
715
+ Draw_stroke_pattern_eq(VALUE self, VALUE pattern)
716
+ {
717
+ Draw *draw;
718
+
719
+ rb_check_frozen(self);
720
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
721
+
722
+ if (draw->info->stroke_pattern != NULL)
723
+ {
724
+ // Do not trace destruction
725
+ DestroyImage(draw->info->stroke_pattern);
726
+ draw->info->stroke_pattern = NULL;
727
+ }
728
+
729
+ if (!NIL_P(pattern))
730
+ {
731
+ Image *image;
732
+
733
+ // DestroyDrawInfo destroys the clone
734
+ pattern = rm_cur_image(pattern);
735
+ image = rm_check_destroyed(pattern);
736
+ // Do not trace creation
737
+ draw->info->stroke_pattern = rm_clone_image(image);
738
+ }
739
+
740
+ return pattern;
741
+ }
742
+
743
+
744
+ /**
745
+ * Set stroke width.
746
+ *
747
+ * @param stroke_width [Float] the stroke width
748
+ * @return [Float] the given stroke width
749
+ */
750
+ VALUE
751
+ Draw_stroke_width_eq(VALUE self, VALUE stroke_width)
752
+ {
753
+ Draw *draw;
754
+
755
+ rb_check_frozen(self);
756
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
757
+ draw->info->stroke_width = NUM2DBL(stroke_width);
758
+ return stroke_width;
759
+ }
760
+
761
+
762
+ /**
763
+ * Set whether to enable text antialias.
764
+ *
765
+ * @param text_antialias [Boolean] true if enable text antialias
766
+ * @return [Boolean] the given value
767
+ */
768
+ VALUE
769
+ Draw_text_antialias_eq(VALUE self, VALUE text_antialias)
770
+ {
771
+ Draw *draw;
772
+
773
+ rb_check_frozen(self);
774
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
775
+ draw->info->text_antialias = (MagickBooleanType) RTEST(text_antialias);
776
+ return text_antialias;
777
+ }
778
+
779
+
780
+ /**
781
+ * Accept an image as a fill pattern. This is alias of {Draw#fill_pattern=}.
782
+ *
783
+ * @param image [Magick::Image] the image to tile
784
+ * @return [Magick::Image] the given image
785
+ */
786
+ VALUE
787
+ Draw_tile_eq(VALUE self, VALUE image)
788
+ {
789
+ return Draw_fill_pattern_eq(self, image);
790
+ }
791
+
792
+
793
+ /**
794
+ * Set undercolor.
795
+ *
796
+ * @param undercolor [Magick::Pixel, String] the undercolor
797
+ * @return [Magick::Pixel, String] the given undercolor
798
+ */
799
+ VALUE
800
+ Draw_undercolor_eq(VALUE self, VALUE undercolor)
801
+ {
802
+ Draw *draw;
803
+
804
+ rb_check_frozen(self);
805
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
806
+ Color_to_PixelColor(&draw->info->undercolor, undercolor);
807
+ return undercolor;
808
+ }
809
+
810
+
811
+ /**
812
+ * Annotates an image with text.
813
+ *
814
+ * - Additional Draw attribute methods may be called in the optional block,
815
+ * which is executed in the context of an Draw object.
816
+ *
817
+ * @param image_arg [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an
818
+ * imagelist, uses the current image.
819
+ * @param width_arg [Numeric] the width
820
+ * @param height_arg [Numeric] the height
821
+ * @param x_arg [Numeric] x position
822
+ * @param y_arg [Numeric] y position
823
+ * @param text [String] the annotation text
824
+ * @return [Magick::Draw] self
825
+ */
826
+ VALUE Draw_annotate(
827
+ VALUE self,
828
+ VALUE image_arg,
829
+ VALUE width_arg,
830
+ VALUE height_arg,
831
+ VALUE x_arg,
832
+ VALUE y_arg,
833
+ VALUE text)
834
+ {
835
+ Draw *draw;
836
+ Image *image;
837
+ unsigned long width, height;
838
+ long x, y;
839
+ AffineMatrix keep;
840
+ char geometry_str[100];
841
+ char *embed_text;
842
+ #if defined(IMAGEMAGICK_7)
843
+ ExceptionInfo *exception;
844
+ #endif
845
+
846
+ // Save the affine matrix in case it is modified by
847
+ // Draw#rotation=
848
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
849
+ keep = draw->info->affine;
850
+
851
+ image_arg = rm_cur_image(image_arg);
852
+ image = rm_check_frozen(image_arg);
853
+
854
+ // If we have an optional parm block, run it in self's context,
855
+ // allowing the app a chance to modify the object's attributes
856
+ if (rb_block_given_p())
857
+ {
858
+ rb_yield(self);
859
+ }
860
+
861
+ // Translate & store in Draw structure
862
+ embed_text = StringValueCStr(text);
863
+ #if defined(IMAGEMAGICK_7)
864
+ exception = AcquireExceptionInfo();
865
+ draw->info->text = InterpretImageProperties(NULL, image, embed_text, exception);
866
+ if (rm_should_raise_exception(exception, RetainExceptionRetention))
867
+ {
868
+ if (draw->info->text)
869
+ {
870
+ magick_free(draw->info->text);
871
+ }
872
+ rm_raise_exception(exception);
873
+ }
874
+ #else
875
+ draw->info->text = InterpretImageProperties(NULL, image, embed_text);
876
+ #endif
877
+ if (!draw->info->text)
878
+ {
879
+ #if defined(IMAGEMAGICK_7)
880
+ DestroyExceptionInfo(exception);
881
+ #endif
882
+ rb_raise(rb_eArgError, "no text");
883
+ }
884
+
885
+ // Create geometry string, copy to Draw structure, overriding
886
+ // any previously existing value.
887
+ width = NUM2ULONG(width_arg);
888
+ height = NUM2ULONG(height_arg);
889
+ x = NUM2LONG(x_arg);
890
+ y = NUM2LONG(y_arg);
891
+
892
+ if (width == 0 && height == 0)
893
+ {
894
+ snprintf(geometry_str, sizeof(geometry_str), "%+ld%+ld", x, y);
895
+ }
896
+
897
+ // WxH is non-zero
898
+ else
899
+ {
900
+ snprintf(geometry_str, sizeof(geometry_str), "%lux%lu%+ld%+ld", width, height, x, y);
901
+ }
902
+
903
+ magick_clone_string(&draw->info->geometry, geometry_str);
904
+
905
+ #if defined(IMAGEMAGICK_7)
906
+ GVL_STRUCT_TYPE(AnnotateImage) args = { image, draw->info, exception };
907
+ #else
908
+ GVL_STRUCT_TYPE(AnnotateImage) args = { image, draw->info };
909
+ #endif
910
+ CALL_FUNC_WITHOUT_GVL(GVL_FUNC(AnnotateImage), &args);
911
+
912
+ magick_free(draw->info->text);
913
+ draw->info->text = NULL;
914
+ draw->info->affine = keep;
915
+
916
+ #if defined(IMAGEMAGICK_7)
917
+ CHECK_EXCEPTION();
918
+ DestroyExceptionInfo(exception);
919
+ #else
920
+ rm_check_image_exception(image, RetainOnError);
921
+ #endif
922
+
923
+ return self;
924
+ }
925
+
926
+
927
+ /**
928
+ * Clones this object.
929
+ *
930
+ * @return [Magick::Draw] the cloned object
931
+ */
932
+ VALUE
933
+ Draw_clone(VALUE self)
934
+ {
935
+ VALUE clone;
936
+
937
+ clone = Draw_dup(self);
938
+ if (OBJ_FROZEN(self))
939
+ {
940
+ OBJ_FREEZE(clone);
941
+ }
942
+
943
+ RB_GC_GUARD(clone);
944
+
945
+ return clone;
946
+ }
947
+
948
+
949
+ /**
950
+ * Draw the image.
951
+ *
952
+ * @overload composite(x, y, width, height, image)
953
+ * @param x [Numeric] x position
954
+ * @param y [Numeric] y position
955
+ * @param width [Numeric] the width
956
+ * @param height [Numeric] the height
957
+ * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an
958
+ * imagelist, uses the current image.
959
+ *
960
+ * @overload composite(x, y, width, height, image, composite_op = Magick::OverCompositeOp)
961
+ * - The "image" argument can be either an ImageList object or an Image
962
+ * argument.
963
+ * @param x [Numeric] x position
964
+ * @param y [Numeric] y position
965
+ * @param width [Numeric] the width
966
+ * @param height [Numeric] the height
967
+ * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an
968
+ * imagelist, uses the current image.
969
+ * @param composite_op [Magick::CompositeOperator] the operator
970
+ *
971
+ * @return [Magick::Draw] self
972
+ */
973
+ VALUE
974
+ Draw_composite(int argc, VALUE *argv, VALUE self)
975
+ {
976
+ Draw *draw;
977
+ const char *op;
978
+ double x, y, width, height;
979
+ CompositeOperator composite_op;
980
+ VALUE image;
981
+ Image *comp_img;
982
+ struct TmpFile_Name *tmpfile_name;
983
+ char name[MaxTextExtent];
984
+ // Buffer for "image" primitive
985
+ char primitive[MaxTextExtent];
986
+
987
+ if (argc < 5 || argc > 6)
988
+ {
989
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 5 or 6)", argc);
990
+ }
991
+
992
+ // Retrieve the image to composite
993
+ image = rm_cur_image(argv[4]);
994
+ comp_img = rm_check_destroyed(image);
995
+
996
+ x = NUM2DBL(argv[0]);
997
+ y = NUM2DBL(argv[1]);
998
+ width = NUM2DBL(argv[2]);
999
+ height = NUM2DBL(argv[3]);
1000
+
1001
+ composite_op = OverCompositeOp;
1002
+ if (argc == 6)
1003
+ {
1004
+ VALUE_TO_ENUM(argv[5], composite_op, CompositeOperator);
1005
+ }
1006
+
1007
+ op = CommandOptionToMnemonic(MagickComposeOptions, composite_op);
1008
+ if (rm_strcasecmp("Unrecognized", op) == 0)
1009
+ {
1010
+ rb_raise(rb_eArgError, "unknown composite operator (%d)", composite_op);
1011
+ }
1012
+
1013
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
1014
+
1015
+ // Create a temp copy of the composite image
1016
+ rm_write_temp_image(comp_img, name, sizeof(name));
1017
+
1018
+ // Add the temp filename to the filename array.
1019
+ // Use Magick storage since we need to keep the list around
1020
+ // until destroy_Draw is called.
1021
+ tmpfile_name = (struct TmpFile_Name *)magick_malloc(sizeof(struct TmpFile_Name) + rm_strnlen_s(name, sizeof(name)));
1022
+ strcpy(tmpfile_name->name, name);
1023
+ tmpfile_name->next = draw->tmpfile_ary;
1024
+ draw->tmpfile_ary = tmpfile_name;
1025
+
1026
+ // Form the drawing primitive
1027
+ snprintf(primitive, sizeof(primitive), "image %s %g,%g,%g,%g '%s'", op, x, y, width, height, name);
1028
+
1029
+
1030
+ // Send "primitive" to self.
1031
+ rb_funcall(self, rb_intern("primitive"), 1, rb_str_new2(primitive));
1032
+
1033
+ RB_GC_GUARD(image);
1034
+
1035
+ return self;
1036
+ }
1037
+
1038
+
1039
+ /**
1040
+ * Execute the stored drawing primitives on the current image.
1041
+ *
1042
+ * @param image_arg [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an
1043
+ * imagelist, uses the current image.
1044
+ * @return [Magick::Draw] self
1045
+ */
1046
+ VALUE
1047
+ Draw_draw(VALUE self, VALUE image_arg)
1048
+ {
1049
+ Draw *draw;
1050
+ Image *image;
1051
+ #if defined(IMAGEMAGICK_7)
1052
+ ExceptionInfo *exception;
1053
+ #endif
1054
+
1055
+ image_arg = rm_cur_image(image_arg);
1056
+ image = rm_check_frozen(image_arg);
1057
+
1058
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
1059
+ if (draw->primitives == 0)
1060
+ {
1061
+ rb_raise(rb_eArgError, "nothing to draw");
1062
+ }
1063
+
1064
+ // Point the DrawInfo structure at the current set of primitives.
1065
+ magick_clone_string(&(draw->info->primitive), StringValueCStr(draw->primitives));
1066
+
1067
+ #if defined(IMAGEMAGICK_7)
1068
+ exception = AcquireExceptionInfo();
1069
+ GVL_STRUCT_TYPE(DrawImage) args = { image, draw->info, exception };
1070
+ #else
1071
+ GVL_STRUCT_TYPE(DrawImage) args = { image, draw->info };
1072
+ #endif
1073
+ CALL_FUNC_WITHOUT_GVL(GVL_FUNC(DrawImage), &args);
1074
+
1075
+ magick_free(draw->info->primitive);
1076
+ draw->info->primitive = NULL;
1077
+
1078
+ #if defined(IMAGEMAGICK_7)
1079
+ CHECK_EXCEPTION();
1080
+ DestroyExceptionInfo(exception);
1081
+ #else
1082
+ rm_check_image_exception(image, RetainOnError);
1083
+ #endif
1084
+
1085
+ return self;
1086
+ }
1087
+
1088
+
1089
+ /**
1090
+ * Duplicate a Draw object.
1091
+ *
1092
+ * - Constructs a new Draw object, then calls initialize_copy.
1093
+ *
1094
+ * @return [Magick::Draw] the duplicated object
1095
+ */
1096
+ VALUE
1097
+ Draw_dup(VALUE self)
1098
+ {
1099
+ Draw *draw;
1100
+ VALUE dup;
1101
+
1102
+ draw = ALLOC(Draw);
1103
+ memset(draw, 0, sizeof(Draw));
1104
+ dup = TypedData_Wrap_Struct(CLASS_OF(self), &rm_draw_data_type, draw);
1105
+ RB_GC_GUARD(dup);
1106
+
1107
+ return rb_funcall(dup, rm_ID_initialize_copy, 1, self);
1108
+ }
1109
+
1110
+
1111
+ /**
1112
+ * Returns measurements for a given font and text string.
1113
+ *
1114
+ * - If the image argument has been omitted, use a dummy image, but make sure
1115
+ * the text has none of the special characters that refer to image
1116
+ * attributes.
1117
+ *
1118
+ * @overload get_type_metrics(text)
1119
+ * @param text [String] The string to be rendered.
1120
+ *
1121
+ * @overload get_type_metrics(image, text)
1122
+ * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an
1123
+ * imagelist, uses the current image.
1124
+ * @param text [String] The string to be rendered.
1125
+ *
1126
+ * @return [Magick::TypeMetric] The information for a specific string if rendered on a image.
1127
+ */
1128
+ VALUE
1129
+ Draw_get_type_metrics(
1130
+ int argc,
1131
+ VALUE *argv,
1132
+ VALUE self)
1133
+ {
1134
+ return get_type_metrics(argc, argv, self, GVL_FUNC(GetTypeMetrics));
1135
+ }
1136
+
1137
+
1138
+ /**
1139
+ * Returns measurements for a given font and text string.
1140
+ *
1141
+ * - If the image argument has been omitted, use a dummy image, but make sure
1142
+ * the text has none of the special characters that refer to image
1143
+ * attributes.
1144
+ *
1145
+ * @overload get_multiline_type_metrics(text)
1146
+ * @param text [String] The string to be rendered.
1147
+ *
1148
+ * @overload Draw#get_multiline_type_metrics(image, text)
1149
+ * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an
1150
+ * imagelist, uses the current image.
1151
+ * @param text [String] The string to be rendered.
1152
+ *
1153
+ * @return [Magick::TypeMetric] The information for a specific string if rendered on a image.
1154
+ */
1155
+ VALUE
1156
+ Draw_get_multiline_type_metrics(
1157
+ int argc,
1158
+ VALUE *argv,
1159
+ VALUE self)
1160
+ {
1161
+ return get_type_metrics(argc, argv, self, GVL_FUNC(GetMultilineTypeMetrics));
1162
+ }
1163
+
1164
+
1165
+ /**
1166
+ * Initialize clone, dup methods.
1167
+ *
1168
+ * @param orig the original object
1169
+ * @return [Magick::Draw] self
1170
+ */
1171
+ VALUE Draw_init_copy(VALUE self, VALUE orig)
1172
+ {
1173
+ Draw *copy, *original;
1174
+
1175
+ TypedData_Get_Struct(orig, Draw, &rm_draw_data_type, original);
1176
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, copy);
1177
+
1178
+ copy->info = CloneDrawInfo(NULL, original->info);
1179
+ if (!copy->info)
1180
+ {
1181
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
1182
+ }
1183
+
1184
+ if (original->primitives)
1185
+ {
1186
+ copy->primitives = rb_str_dup(original->primitives);
1187
+ }
1188
+
1189
+ return self;
1190
+ }
1191
+
1192
+
1193
+ /**
1194
+ * Initialize Draw object.
1195
+ *
1196
+ * @return [Magick::Draw] self
1197
+ */
1198
+ VALUE
1199
+ Draw_initialize(VALUE self)
1200
+ {
1201
+ Draw *draw, *draw_options;
1202
+ VALUE options;
1203
+
1204
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
1205
+
1206
+ options = new_DrawOptions();
1207
+ TypedData_Get_Struct(options, Draw, &rm_draw_data_type, draw_options);
1208
+ draw->info = draw_options->info;
1209
+ draw_options->info = NULL;
1210
+
1211
+ RB_GC_GUARD(options);
1212
+
1213
+ return self;
1214
+ }
1215
+
1216
+
1217
+ /**
1218
+ * Display the primitives.
1219
+ *
1220
+ * @return [String] the draw primitives or the Ruby string "(no primitives defined)"
1221
+ * if they are not defined
1222
+ */
1223
+ VALUE
1224
+ Draw_inspect(VALUE self)
1225
+ {
1226
+ Draw *draw;
1227
+
1228
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
1229
+ return draw->primitives ? draw->primitives : rb_str_new2("(no primitives defined)");
1230
+ }
1231
+
1232
+
1233
+ /**
1234
+ * Create a new Draw object.
1235
+ *
1236
+ * @return [Magick::Draw] a new Draw object
1237
+ */
1238
+ VALUE Draw_alloc(VALUE klass)
1239
+ {
1240
+ Draw *draw;
1241
+ VALUE draw_obj;
1242
+
1243
+ draw = ALLOC(Draw);
1244
+ memset(draw, 0, sizeof(Draw));
1245
+ draw_obj = TypedData_Wrap_Struct(klass, &rm_draw_data_type, draw);
1246
+
1247
+ RB_GC_GUARD(draw_obj);
1248
+
1249
+ return draw_obj;
1250
+ }
1251
+
1252
+
1253
+ /**
1254
+ * Add a drawing primitive to the list of primitives in the Draw object.
1255
+ *
1256
+ * @param primitive [String] the primitive to add
1257
+ * @return [Magick::Draw] self
1258
+ */
1259
+ VALUE
1260
+ Draw_primitive(VALUE self, VALUE primitive)
1261
+ {
1262
+ Draw *draw;
1263
+
1264
+ rb_check_frozen(self);
1265
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
1266
+
1267
+ if (draw->primitives == (VALUE)0)
1268
+ {
1269
+ draw->primitives = primitive;
1270
+ }
1271
+ else
1272
+ {
1273
+ draw->primitives = rb_str_plus(draw->primitives, rb_str_new2("\n"));
1274
+ draw->primitives = rb_str_concat(draw->primitives, primitive);
1275
+ }
1276
+
1277
+ return self;
1278
+ }
1279
+
1280
+ #ifdef HAVE_RB_GC_MARK_MOVABLE
1281
+ /**
1282
+ * Compact the objects.
1283
+ *
1284
+ * No Ruby usage (internal function)
1285
+ *
1286
+ * @param drawptr pointer to a Draw object
1287
+ */
1288
+ static void
1289
+ Draw_compact(void *drawptr)
1290
+ {
1291
+ Draw *draw = (Draw *)drawptr;
1292
+
1293
+ if (draw->primitives != (VALUE)0)
1294
+ {
1295
+ draw->primitives = rb_gc_location(draw->primitives);
1296
+ }
1297
+ }
1298
+ #endif
1299
+
1300
+ /**
1301
+ * Mark referenced objects.
1302
+ *
1303
+ * No Ruby usage (internal function)
1304
+ *
1305
+ * @param drawptr pointer to a Draw object
1306
+ */
1307
+ static void
1308
+ Draw_mark(void *drawptr)
1309
+ {
1310
+ Draw *draw = (Draw *)drawptr;
1311
+
1312
+ if (draw->primitives != (VALUE)0)
1313
+ {
1314
+ #ifdef HAVE_RB_GC_MARK_MOVABLE
1315
+ rb_gc_mark_movable(draw->primitives);
1316
+ #else
1317
+ rb_gc_mark(draw->primitives);
1318
+ #endif
1319
+ }
1320
+ }
1321
+
1322
+
1323
+ /**
1324
+ * Free the memory associated with an Draw object.
1325
+ *
1326
+ * No Ruby usage (internal function)
1327
+ *
1328
+ * @param drawptr pointer to a Draw object
1329
+ */
1330
+ static void
1331
+ Draw_destroy(void *drawptr)
1332
+ {
1333
+ Draw *draw = (Draw *)drawptr;
1334
+
1335
+ if (draw->info)
1336
+ {
1337
+ DestroyDrawInfo(draw->info);
1338
+ draw->info = NULL;
1339
+ }
1340
+
1341
+ // Erase any temporary image files.
1342
+ while (draw->tmpfile_ary)
1343
+ {
1344
+ struct TmpFile_Name *tmpfile_name;
1345
+
1346
+ tmpfile_name = draw->tmpfile_ary;
1347
+ draw->tmpfile_ary = draw->tmpfile_ary->next;
1348
+ rm_delete_temp_image(tmpfile_name->name);
1349
+ magick_free(tmpfile_name);
1350
+ }
1351
+
1352
+ xfree(drawptr);
1353
+ }
1354
+
1355
+ /**
1356
+ * Get Draw object size.
1357
+ *
1358
+ * No Ruby usage (internal function)
1359
+ *
1360
+ * @param infoptr pointer to the Draw object
1361
+ */
1362
+ static size_t
1363
+ Draw_memsize(const void *drawptr)
1364
+ {
1365
+ return sizeof(Draw);
1366
+ }
1367
+
1368
+ /**
1369
+ * Allocate & initialize a DrawOptions object.
1370
+ *
1371
+ * No Ruby usage (internal function)
1372
+ *
1373
+ * @return a new DrawOptions object
1374
+ */
1375
+ static VALUE
1376
+ new_DrawOptions(void)
1377
+ {
1378
+ return DrawOptions_initialize(Draw_alloc(Class_DrawOptions));
1379
+ }
1380
+
1381
+
1382
+ /**
1383
+ * Create a DrawOptions object.
1384
+ *
1385
+ * - The DrawOptions class is the same as the Draw class except is has only
1386
+ * the attribute writer functions
1387
+ *
1388
+ * @return [Magick::Image::DrawOptions] a new DrawOptions object
1389
+ */
1390
+ VALUE
1391
+ DrawOptions_alloc(VALUE klass)
1392
+ {
1393
+ Draw *draw_options;
1394
+ VALUE draw_options_obj;
1395
+
1396
+ draw_options = ALLOC(Draw);
1397
+ memset(draw_options, 0, sizeof(Draw));
1398
+ draw_options_obj = TypedData_Wrap_Struct(klass, &rm_draw_data_type, draw_options);
1399
+
1400
+ RB_GC_GUARD(draw_options_obj);
1401
+
1402
+ return draw_options_obj;
1403
+ }
1404
+
1405
+
1406
+ /**
1407
+ * Initialize a DrawOptions object.
1408
+ *
1409
+ * @return [Magick::Image::DrawOptions] self
1410
+ */
1411
+ VALUE
1412
+ DrawOptions_initialize(VALUE self)
1413
+ {
1414
+ Draw *draw_options;
1415
+
1416
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw_options);
1417
+ draw_options->info = AcquireDrawInfo();
1418
+ if (!draw_options->info)
1419
+ {
1420
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
1421
+ }
1422
+
1423
+ if (rb_block_given_p())
1424
+ {
1425
+ rb_yield(self);
1426
+ }
1427
+
1428
+ return self;
1429
+ }
1430
+
1431
+
1432
+ /**
1433
+ * Allocate a new Magick::Image::PolaroidOptions object.
1434
+ *
1435
+ * - Internally a PolaroidOptions object is the same as a Draw object. The
1436
+ * methods are implemented by Draw methods in rmdraw.cpp.
1437
+ *
1438
+ * @return [Magick::Image::PolaroidOptions] a new PolaroidOptions object
1439
+ */
1440
+ VALUE
1441
+ PolaroidOptions_alloc(VALUE klass)
1442
+ {
1443
+ VALUE polaroid_obj;
1444
+ ImageInfo *image_info;
1445
+ Draw *draw;
1446
+
1447
+ image_info = CloneImageInfo(NULL);
1448
+
1449
+ draw = ALLOC(Draw);
1450
+ memset(draw, 0, sizeof(*draw));
1451
+
1452
+ draw->info = CloneDrawInfo(image_info, (DrawInfo *) NULL);
1453
+ (void) DestroyImageInfo(image_info);
1454
+
1455
+ polaroid_obj = TypedData_Wrap_Struct(klass, &rm_draw_data_type, draw);
1456
+
1457
+ RB_GC_GUARD(polaroid_obj);
1458
+
1459
+ return polaroid_obj;
1460
+ }
1461
+
1462
+
1463
+ /**
1464
+ * Initialize a PolaroidOptions object.
1465
+ *
1466
+ * @yield [opt]
1467
+ * @yieldparam opt [Magick::Image::PolaroidOptions] self
1468
+ * @return [Magick::Image::PolaroidOptions] self
1469
+ */
1470
+ VALUE
1471
+ PolaroidOptions_initialize(VALUE self)
1472
+ {
1473
+ Draw *draw;
1474
+ ExceptionInfo *exception;
1475
+
1476
+ // Default shadow color
1477
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
1478
+
1479
+ exception = AcquireExceptionInfo();
1480
+ QueryColorCompliance("gray75", AllCompliance, &draw->shadow_color, exception);
1481
+ CHECK_EXCEPTION();
1482
+ QueryColorCompliance("#dfdfdf", AllCompliance, &draw->info->border_color, exception);
1483
+ CHECK_EXCEPTION();
1484
+ DestroyExceptionInfo(exception);
1485
+
1486
+ if (rb_block_given_p())
1487
+ {
1488
+ rb_yield(self);
1489
+ }
1490
+
1491
+ return self;
1492
+ }
1493
+
1494
+
1495
+ /**
1496
+ * Allocate a PolaroidOptions instance.
1497
+ *
1498
+ * No Ruby usage (internal function)
1499
+ *
1500
+ * @return new PolaroidOptions object
1501
+ */
1502
+ VALUE
1503
+ rm_polaroid_new(void)
1504
+ {
1505
+ return PolaroidOptions_initialize(PolaroidOptions_alloc(Class_PolaroidOptions));
1506
+ }
1507
+
1508
+
1509
+ /**
1510
+ * Set the shadow color attribute.
1511
+ *
1512
+ * @param shadow [Magick::Pixel, String] the shadow color
1513
+ * @return [Magick::Pixel, String] the given shadow color
1514
+ */
1515
+ VALUE
1516
+ PolaroidOptions_shadow_color_eq(VALUE self, VALUE shadow)
1517
+ {
1518
+ Draw *draw;
1519
+
1520
+ rb_check_frozen(self);
1521
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
1522
+ Color_to_PixelColor(&draw->shadow_color, shadow);
1523
+ return shadow;
1524
+ }
1525
+
1526
+
1527
+ /**
1528
+ * Set the border color.
1529
+ *
1530
+ * @param border [Magick::Pixel, String] the border color
1531
+ * @return [Magick::Pixel, String] the given border color
1532
+ */
1533
+ VALUE
1534
+ PolaroidOptions_border_color_eq(VALUE self, VALUE border)
1535
+ {
1536
+ Draw *draw;
1537
+
1538
+ rb_check_frozen(self);
1539
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
1540
+ Color_to_PixelColor(&draw->info->border_color, border);
1541
+ return border;
1542
+ }
1543
+
1544
+
1545
+ /**
1546
+ * Create a dummy object of an image class.
1547
+ *
1548
+ * No Ruby usage (internal function)
1549
+ *
1550
+ * @param klass the class for which to create a dummy
1551
+ * @return the newly allocated dummy
1552
+ */
1553
+ static VALUE
1554
+ get_dummy_tm_img(VALUE klass)
1555
+ {
1556
+ #define DUMMY_IMG_CLASS_VAR "@@_dummy_img_"
1557
+ VALUE dummy_img = 0;
1558
+
1559
+ if (rb_cvar_defined(klass, rb_intern(DUMMY_IMG_CLASS_VAR)) != Qtrue)
1560
+ {
1561
+ Info *info;
1562
+ Image *image;
1563
+
1564
+ info = CloneImageInfo(NULL);
1565
+ if (!info)
1566
+ {
1567
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
1568
+ }
1569
+ image = rm_acquire_image(info);
1570
+ DestroyImageInfo(info);
1571
+
1572
+ if (!image)
1573
+ {
1574
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
1575
+ }
1576
+ dummy_img = rm_image_new(image);
1577
+
1578
+ rb_cv_set(klass, DUMMY_IMG_CLASS_VAR, dummy_img);
1579
+ }
1580
+ dummy_img = rb_cv_get(klass, DUMMY_IMG_CLASS_VAR);
1581
+
1582
+ RB_GC_GUARD(dummy_img);
1583
+
1584
+ return dummy_img;
1585
+ }
1586
+
1587
+
1588
+ // aliases for common use of structure types; GetMultilineTypeMetrics, GetTypeMetrics
1589
+ typedef GVL_STRUCT_TYPE(GetTypeMetrics) GVL_STRUCT_TYPE(get_type_metrics);
1590
+
1591
+ /**
1592
+ * Call a get-type-metrics function.
1593
+ *
1594
+ * No Ruby usage (internal function)
1595
+ *
1596
+ * Notes:
1597
+ * - called by Draw_get_type_metrics and Draw_get_multiline_type_metrics
1598
+ *
1599
+ * @param argc number of input arguments
1600
+ * @param argv array of input arguments
1601
+ * @param self this object
1602
+ * @param getter which type metrics to get
1603
+ * @return the type metrics
1604
+ * @see Draw_get_type_metrics
1605
+ * @see Draw_get_multiline_type_metrics
1606
+ */
1607
+ static VALUE
1608
+ get_type_metrics(int argc, VALUE *argv, VALUE self, gvl_function_t fp)
1609
+ {
1610
+ Image *image;
1611
+ Draw *draw;
1612
+ VALUE t;
1613
+ TypeMetric metrics;
1614
+ char *text = NULL;
1615
+ size_t text_l;
1616
+ MagickBooleanType okay;
1617
+ #if defined(IMAGEMAGICK_7)
1618
+ ExceptionInfo *exception;
1619
+ #endif
1620
+
1621
+ switch (argc)
1622
+ {
1623
+ case 1: // use default image
1624
+ text = rm_str2cstr(argv[0], &text_l);
1625
+ TypedData_Get_Struct(get_dummy_tm_img(CLASS_OF(self)), Image, &rm_image_data_type, image);
1626
+ break;
1627
+ case 2:
1628
+ t = rm_cur_image(argv[0]);
1629
+ image = rm_check_destroyed(t);
1630
+ text = rm_str2cstr(argv[1], &text_l);
1631
+ break; // okay
1632
+ default:
1633
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 2)", argc);
1634
+ break;
1635
+ }
1636
+
1637
+ if (text_l == 0)
1638
+ {
1639
+ rb_raise(rb_eArgError, "no text to measure");
1640
+ }
1641
+
1642
+ TypedData_Get_Struct(self, Draw, &rm_draw_data_type, draw);
1643
+ #if defined(IMAGEMAGICK_7)
1644
+ exception = AcquireExceptionInfo();
1645
+ draw->info->text = InterpretImageProperties(NULL, image, text, exception);
1646
+ if (rm_should_raise_exception(exception, RetainExceptionRetention))
1647
+ {
1648
+ if (draw->info->text)
1649
+ {
1650
+ magick_free(draw->info->text);
1651
+ }
1652
+ rm_raise_exception(exception);
1653
+ }
1654
+ #else
1655
+ draw->info->text = InterpretImageProperties(NULL, image, text);
1656
+ #endif
1657
+ if (!draw->info->text)
1658
+ {
1659
+ #if defined(IMAGEMAGICK_7)
1660
+ DestroyExceptionInfo(exception);
1661
+ #endif
1662
+ rb_raise(rb_eArgError, "no text to measure");
1663
+ }
1664
+
1665
+ #if defined(IMAGEMAGICK_7)
1666
+ GVL_STRUCT_TYPE(get_type_metrics) args = { image, draw->info, &metrics, exception };
1667
+ #else
1668
+ GVL_STRUCT_TYPE(get_type_metrics) args = { image, draw->info, &metrics };
1669
+ #endif
1670
+ void *ret = CALL_FUNC_WITHOUT_GVL(fp, &args);
1671
+ okay = static_cast<MagickBooleanType>(reinterpret_cast<intptr_t &>(ret));
1672
+
1673
+ magick_free(draw->info->text);
1674
+ draw->info->text = NULL;
1675
+
1676
+ if (!okay)
1677
+ {
1678
+ #if defined(IMAGEMAGICK_7)
1679
+ CHECK_EXCEPTION();
1680
+ DestroyExceptionInfo(exception);
1681
+ #else
1682
+ rm_check_image_exception(image, RetainOnError);
1683
+ #endif
1684
+
1685
+ // Shouldn't get here...
1686
+ rb_raise(rb_eRuntimeError, "Can't measure text. Are the fonts installed? "
1687
+ "Is the FreeType library installed?");
1688
+ }
1689
+ #if defined(IMAGEMAGICK_7)
1690
+ DestroyExceptionInfo(exception);
1691
+ #endif
1692
+
1693
+ RB_GC_GUARD(t);
1694
+
1695
+ return Import_TypeMetric(&metrics);
1696
+ }