rmagick-windows 2.16.1

Sign up to get free protection for your applications and to get access to all the features.
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,2022 @@
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.c
9
+ * @version $Id: rmdraw.c,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
+ static void mark_Draw(void *);
17
+ static void destroy_Draw(void *);
18
+ static VALUE new_DrawOptions(void);
19
+
20
+ /** Method that gets type metrics */
21
+ typedef MagickBooleanType (get_type_metrics_func_t)(Image *, const DrawInfo *, TypeMetric *);
22
+ static VALUE get_type_metrics(int, VALUE *, VALUE, get_type_metrics_func_t);
23
+
24
+
25
+ /**
26
+ * Set the affine matrix from an Magick::AffineMatrix.
27
+ *
28
+ * Ruby usage:
29
+ * - @verbatim Draw#affine= @endverbatim
30
+ *
31
+ * @param self this object
32
+ * @param matrix the affine matrix to set
33
+ * @return self
34
+ */
35
+ VALUE
36
+ Draw_affine_eq(VALUE self, VALUE matrix)
37
+ {
38
+ Draw *draw;
39
+
40
+ rb_check_frozen(self);
41
+ Data_Get_Struct(self, Draw, draw);
42
+ Export_AffineMatrix(&draw->info->affine, matrix);
43
+ return self;
44
+ }
45
+
46
+
47
+ /**
48
+ * Set the text alignment.
49
+ *
50
+ * Ruby usage:
51
+ * - @verbatim Draw#align= @endverbatim
52
+ *
53
+ * @param self this object
54
+ * @param align the alignment
55
+ * @return self
56
+ */
57
+ VALUE
58
+ Draw_align_eq(VALUE self, VALUE align)
59
+ {
60
+ Draw *draw;
61
+
62
+ rb_check_frozen(self);
63
+ Data_Get_Struct(self, Draw, draw);
64
+ VALUE_TO_ENUM(align, draw->info->align, AlignType);
65
+ return self;
66
+ }
67
+
68
+
69
+ /**
70
+ * Decorate attribute writer.
71
+ *
72
+ * Ruby usage:
73
+ * - @verbatim Draw#decorate= @endverbatim
74
+ *
75
+ * @param self this object
76
+ * @param decorate the decorate
77
+ * @return self
78
+ */
79
+ VALUE
80
+ Draw_decorate_eq(VALUE self, VALUE decorate)
81
+ {
82
+ Draw *draw;
83
+
84
+ rb_check_frozen(self);
85
+ Data_Get_Struct(self, Draw, draw);
86
+ VALUE_TO_ENUM(decorate, draw->info->decorate, DecorationType);
87
+ return self;
88
+ }
89
+
90
+
91
+ /**
92
+ * Density attribute writer.
93
+ *
94
+ * Ruby usage:
95
+ * - @verbatim Draw#density= @endverbatim
96
+ *
97
+ * @param self this object
98
+ * @param density the density
99
+ * @return self
100
+ */
101
+ VALUE
102
+ Draw_density_eq(VALUE self, VALUE density)
103
+ {
104
+ Draw *draw;
105
+
106
+ rb_check_frozen(self);
107
+ Data_Get_Struct(self, Draw, draw);
108
+ magick_clone_string(&draw->info->density, StringValuePtr(density));
109
+
110
+ return self;
111
+ }
112
+
113
+
114
+ /**
115
+ * Encoding attribute writer.
116
+ *
117
+ * Ruby usage:
118
+ * - @verbatim Draw#encoding= @endverbatim
119
+ *
120
+ * @param self this object
121
+ * @param encoding the encoding
122
+ * @return self
123
+ */
124
+ VALUE
125
+ Draw_encoding_eq(VALUE self, VALUE encoding)
126
+ {
127
+ Draw *draw;
128
+
129
+ rb_check_frozen(self);
130
+ Data_Get_Struct(self, Draw, draw);
131
+ magick_clone_string(&draw->info->encoding, StringValuePtr(encoding));
132
+
133
+ return self;
134
+ }
135
+
136
+
137
+ /**
138
+ * Fill attribute writer.
139
+ *
140
+ * Ruby usage:
141
+ * - @verbatim Draw#fill= @endverbatim
142
+ *
143
+ * @param self this object
144
+ * @param fill the fill
145
+ * @return self
146
+ */
147
+ VALUE
148
+ Draw_fill_eq(VALUE self, VALUE fill)
149
+ {
150
+ Draw *draw;
151
+
152
+ rb_check_frozen(self);
153
+ Data_Get_Struct(self, Draw, draw);
154
+ Color_to_PixelPacket(&draw->info->fill, fill);
155
+ return self;
156
+ }
157
+
158
+
159
+ /**
160
+ * Accept an image as a fill pattern.
161
+ *
162
+ * Ruby usage:
163
+ * - @verbatim Draw#fill_pattern= @endverbatim
164
+ *
165
+ * @param self this object
166
+ * @param pattern the fill pattern
167
+ * @return self
168
+ * @see Draw_stroke_pattern_eq
169
+ * @see Draw_tile_eq
170
+ */
171
+ VALUE
172
+ Draw_fill_pattern_eq(VALUE self, VALUE pattern)
173
+ {
174
+ Draw *draw;
175
+ Image *image;
176
+
177
+ rb_check_frozen(self);
178
+ Data_Get_Struct(self, Draw, draw);
179
+
180
+ if (draw->info->fill_pattern != NULL)
181
+ {
182
+ // Do not trace destruction
183
+ DestroyImage(draw->info->fill_pattern);
184
+ draw->info->fill_pattern = NULL;
185
+ }
186
+
187
+ if (!NIL_P(pattern))
188
+ {
189
+ pattern = rm_cur_image(pattern);
190
+ image = rm_check_destroyed(pattern);
191
+ // Do not trace creation
192
+ draw->info->fill_pattern = rm_clone_image(image);
193
+ }
194
+
195
+ return self;
196
+ }
197
+
198
+
199
+ /**
200
+ * Font attribute writer.
201
+ *
202
+ * Ruby usage:
203
+ * - @verbatim Draw#font= @endverbatim
204
+ *
205
+ * @param self this object
206
+ * @param font the font
207
+ * @return self
208
+ */
209
+ VALUE
210
+ Draw_font_eq(VALUE self, VALUE font)
211
+ {
212
+ Draw *draw;
213
+
214
+ rb_check_frozen(self);
215
+ Data_Get_Struct(self, Draw, draw);
216
+ magick_clone_string(&draw->info->font, StringValuePtr(font));
217
+
218
+ return self;
219
+ }
220
+
221
+
222
+ /**
223
+ * Font family attribute writer.
224
+ *
225
+ * Ruby usage:
226
+ * - @verbatim Draw#family= @endverbatim
227
+ *
228
+ * @param self this object
229
+ * @param family the family
230
+ * @return self
231
+ */
232
+ VALUE
233
+ Draw_font_family_eq(VALUE self, VALUE family)
234
+ {
235
+ Draw *draw;
236
+
237
+ rb_check_frozen(self);
238
+ Data_Get_Struct(self, Draw, draw);
239
+ magick_clone_string(&draw->info->family, StringValuePtr(family));
240
+
241
+ return self;
242
+ }
243
+
244
+
245
+ /**
246
+ * Font_stretch attribute writer.
247
+ *
248
+ * Ruby usage:
249
+ * - @verbatim Draw#font_stretch= @endverbatim
250
+ *
251
+ * @param self this object
252
+ * @param stretch the font_stretch
253
+ * @return self
254
+ */
255
+ VALUE
256
+ Draw_font_stretch_eq(VALUE self, VALUE stretch)
257
+ {
258
+ Draw *draw;
259
+
260
+ rb_check_frozen(self);
261
+ Data_Get_Struct(self, Draw, draw);
262
+ VALUE_TO_ENUM(stretch, draw->info->stretch, StretchType);
263
+ return self;
264
+ }
265
+
266
+
267
+ /**
268
+ * Font_style attribute writer.
269
+ *
270
+ * Ruby usage:
271
+ * - @verbatim Draw#font_style= @endverbatim
272
+ *
273
+ * @param self this object
274
+ * @param style the font_style
275
+ * @return self
276
+ */
277
+ VALUE
278
+ Draw_font_style_eq(VALUE self, VALUE style)
279
+ {
280
+ Draw *draw;
281
+
282
+ rb_check_frozen(self);
283
+ Data_Get_Struct(self, Draw, draw);
284
+ VALUE_TO_ENUM(style, draw->info->style, StyleType);
285
+ return self;
286
+ }
287
+
288
+
289
+ /**
290
+ * Font_weight attribute writer.
291
+ *
292
+ * Ruby usage:
293
+ * - @verbatim Draw#font_weight= @endverbatim
294
+ *
295
+ * Notes:
296
+ * - The font weight can be one of the font weight constants or a number
297
+ * between 100 and 900
298
+ *
299
+ * @param self this object
300
+ * @param weight the font_weight
301
+ * @return self
302
+ */
303
+ VALUE
304
+ Draw_font_weight_eq(VALUE self, VALUE weight)
305
+ {
306
+ Draw *draw;
307
+ WeightType w;
308
+
309
+ rb_check_frozen(self);
310
+ Data_Get_Struct(self, Draw, draw);
311
+
312
+ if (FIXNUM_P(weight))
313
+ {
314
+ w = (WeightType) FIX2INT(weight);
315
+ if (w < 100 || w > 900)
316
+ {
317
+ rb_raise(rb_eArgError, "invalid font weight (%d given)", w);
318
+ }
319
+ draw->info->weight = w;
320
+ }
321
+ else
322
+ {
323
+ VALUE_TO_ENUM(weight, w, WeightType);
324
+ switch (w)
325
+ {
326
+ case AnyWeight:
327
+ draw->info->weight = 0;
328
+ break;
329
+ case NormalWeight:
330
+ draw->info->weight = 400;
331
+ break;
332
+ case BoldWeight:
333
+ draw->info->weight = 700;
334
+ break;
335
+ case BolderWeight:
336
+ if (draw->info->weight <= 800)
337
+ draw->info->weight += 100;
338
+ break;
339
+ case LighterWeight:
340
+ if (draw->info->weight >= 100)
341
+ draw->info->weight -= 100;
342
+ break;
343
+ default:
344
+ rb_raise(rb_eArgError, "unknown font weight");
345
+ break;
346
+ }
347
+ }
348
+
349
+ return self;
350
+ }
351
+
352
+
353
+ /**
354
+ * Gravity attribute writer.
355
+ *
356
+ * Ruby usage:
357
+ * - @verbatim Draw#gravity= @endverbatim
358
+ *
359
+ * Notes:
360
+ * - From Magick++'s Image.h header file:
361
+ * Gravity affects text placement in bounding area according to rules:
362
+ * - NorthWestGravity text bottom-left corner placed at top-left
363
+ * - NorthGravity text bottom-center placed at top-center
364
+ * - NorthEastGravity text bottom-right corner placed at top-right
365
+ * - WestGravity text left-center placed at left-center
366
+ * - CenterGravity text center placed at center
367
+ * - EastGravity text right-center placed at right-center
368
+ * - SouthWestGravity text top-left placed at bottom-left
369
+ * - SouthGravity text top-center placed at bottom-center
370
+ * - SouthEastGravity text top-right placed at bottom-right
371
+ *
372
+ * @param self this object
373
+ * @param grav the gravity
374
+ * @return self
375
+ */
376
+ VALUE
377
+ Draw_gravity_eq(VALUE self, VALUE grav)
378
+ {
379
+ Draw *draw;
380
+
381
+ rb_check_frozen(self);
382
+ Data_Get_Struct(self, Draw, draw);
383
+ VALUE_TO_ENUM(grav, draw->info->gravity, GravityType);
384
+
385
+ return self;
386
+ }
387
+
388
+
389
+ /**
390
+ * Space between two letters.
391
+ *
392
+ * Ruby usage:
393
+ * - @verbatim Draw#gravity=float @endverbatim
394
+ *
395
+ * Notes:
396
+ * - New for ImageMagick 6.4.7-8
397
+ *
398
+ * @param self this object
399
+ * @param kerning the kerning
400
+ * @return self
401
+ */
402
+ VALUE
403
+ Draw_kerning_eq(VALUE self, VALUE kerning)
404
+ {
405
+ #if defined(HAVE_ST_KERNING)
406
+ Draw *draw;
407
+
408
+ rb_check_frozen(self);
409
+ Data_Get_Struct(self, Draw, draw);
410
+ draw->info->kerning = NUM2DBL(kerning);
411
+ return self;
412
+ #else
413
+ rm_not_implemented();
414
+ return (VALUE)0;
415
+ self = self;
416
+ kerning = kerning;
417
+ #endif
418
+ }
419
+
420
+
421
+ /**
422
+ * Space between two lines.
423
+ *
424
+ * Ruby usage:
425
+ * - @verbatim Draw#interline_spacing= @endverbatim
426
+ *
427
+ * Notes:
428
+ * - New for ImageMagick 6.5.5-8
429
+ *
430
+ * @param self this object
431
+ * @param spacing the spacing
432
+ * @return self
433
+ */
434
+ VALUE
435
+ Draw_interline_spacing_eq(VALUE self, VALUE spacing)
436
+ {
437
+ #if defined(HAVE_ST_INTERLINE_SPACING)
438
+ Draw *draw;
439
+
440
+ rb_check_frozen(self);
441
+ Data_Get_Struct(self, Draw, draw);
442
+ draw->info->interline_spacing = NUM2DBL(spacing);
443
+ return self;
444
+ #else
445
+ rm_not_implemented();
446
+ return (VALUE)0;
447
+ self = self;
448
+ spacing = spacing;
449
+ #endif
450
+ }
451
+
452
+
453
+ /**
454
+ * Space between two words.
455
+ *
456
+ * Ruby usage:
457
+ * - @verbatim Draw#interword_spacing= @endverbatim
458
+ *
459
+ * Notes:
460
+ * - New for ImageMagick 6.4.8-0
461
+ *
462
+ * @param self this object
463
+ * @param spacing the spacing
464
+ * @return self
465
+ */
466
+ VALUE
467
+ Draw_interword_spacing_eq(VALUE self, VALUE spacing)
468
+ {
469
+ #if defined(HAVE_ST_INTERWORD_SPACING)
470
+ Draw *draw;
471
+
472
+ rb_check_frozen(self);
473
+ Data_Get_Struct(self, Draw, draw);
474
+ draw->info->interword_spacing = NUM2DBL(spacing);
475
+ return self;
476
+ #else
477
+ rm_not_implemented();
478
+ return (VALUE)0;
479
+ self = self;
480
+ spacing = spacing;
481
+ #endif
482
+ }
483
+
484
+
485
+ /**
486
+ * Convert an image to a blob and the blob to a String.
487
+ *
488
+ * No Ruby usage (internal function)
489
+ *
490
+ * Notes:
491
+ * - Returns Qnil if there is no image
492
+ *
493
+ * @param image the Image to convert
494
+ * @return Ruby string representation of image
495
+ * @see str_to_image
496
+ */
497
+ static VALUE
498
+ image_to_str(Image *image)
499
+ {
500
+ VALUE dimg = Qnil;
501
+ unsigned char *blob;
502
+ size_t length;
503
+ Info *info;
504
+ ExceptionInfo *exception;
505
+
506
+ if (image)
507
+ {
508
+ info = CloneImageInfo(NULL);
509
+ exception = AcquireExceptionInfo();
510
+ blob = ImageToBlob(info, image, &length, exception);
511
+ DestroyImageInfo(info);
512
+ CHECK_EXCEPTION();
513
+ DestroyExceptionInfo(exception);
514
+ dimg = rb_str_new((char *)blob, (long)length);
515
+ magick_free((void*)blob);
516
+ }
517
+
518
+ RB_GC_GUARD(dimg);
519
+
520
+ return dimg;
521
+ }
522
+
523
+
524
+ /**
525
+ * Undo the image_to_str, above.
526
+ *
527
+ * No Ruby usage (internal function)
528
+ *
529
+ * Notes:
530
+ * - Returns NULL if the argument is Qnil
531
+ *
532
+ * @param str the Ruby string to convert
533
+ * @return Image represented by str
534
+ * @see image_to_str
535
+ */
536
+ static
537
+ Image *str_to_image(VALUE str)
538
+ {
539
+ Image *image = NULL;
540
+ Info *info;
541
+ ExceptionInfo *exception;
542
+
543
+ if (str != Qnil)
544
+ {
545
+ info = CloneImageInfo(NULL);
546
+ exception = AcquireExceptionInfo();
547
+ image = BlobToImage(info, RSTRING_PTR(str), RSTRING_LEN(str), exception);
548
+ DestroyImageInfo(info);
549
+ CHECK_EXCEPTION();
550
+ DestroyExceptionInfo(exception);
551
+ }
552
+
553
+ return image;
554
+ }
555
+
556
+
557
+ /**
558
+ * Custom marshal for Draw objects.
559
+ *
560
+ * Ruby usage:
561
+ * - @verbatim Draw#marshal_dump @endverbatim
562
+ *
563
+ * Notes:
564
+ * - Instead of trying to replicate Ruby's support for cross-system
565
+ * marshalling, exploit it. Convert the Draw fields to Ruby objects and
566
+ * store them in a hash. Let Ruby marshal the hash.
567
+ * - Commented out code that dumps/loads fields that are used internally by
568
+ * ImageMagick and shouldn't be marshaled. I left the code as placeholders
569
+ * so I'll know which fields have been deliberately omitted.
570
+ *
571
+ * @param self this object
572
+ * @return the marshalled object (as a Ruby hash)
573
+ * @todo Handle gradients when christy gets the new gradient support added (23Dec08)
574
+ */
575
+ VALUE
576
+ Draw_marshal_dump(VALUE self)
577
+ {
578
+ Draw *draw;
579
+ VALUE ddraw;
580
+
581
+ Data_Get_Struct(self, Draw, draw);
582
+
583
+ // Raise an exception if the Draw has a non-NULL gradient or element_reference field
584
+ if (draw->info->element_reference.type != UndefinedReference
585
+ || draw->info->gradient.type != UndefinedGradient)
586
+ {
587
+ rb_raise(rb_eTypeError, "can't dump gradient definition");
588
+ }
589
+
590
+ ddraw = rb_hash_new();
591
+
592
+ // rb_hash_aset(ddraw, CSTR2SYM("primitive"), MAGICK_STRING_TO_OBJ(draw->info->primitive)); internal
593
+ // rb_hash_aset(ddraw, CSTR2SYM("geometry"), MAGICK_STRING_TO_OBJ(draw->info->geometry)); set by "text" primitive
594
+ // rb_hash_aset(ddraw, CSTR2SYM("viewbox"), Import_RectangleInfo(&draw->info->viewbox)); internal
595
+ rb_hash_aset(ddraw, CSTR2SYM("affine"), Import_AffineMatrix(&draw->info->affine));
596
+ rb_hash_aset(ddraw, CSTR2SYM("gravity"), INT2FIX(draw->info->gravity));
597
+ rb_hash_aset(ddraw, CSTR2SYM("fill"), Pixel_from_PixelPacket(&draw->info->fill));
598
+ rb_hash_aset(ddraw, CSTR2SYM("stroke"), Pixel_from_PixelPacket(&draw->info->stroke));
599
+ rb_hash_aset(ddraw, CSTR2SYM("stroke_width"), rb_float_new(draw->info->stroke_width));
600
+ // rb_hash_aset(ddraw, CSTR2SYM("gradient"), Qnil); // not used yet
601
+ rb_hash_aset(ddraw, CSTR2SYM("fill_pattern"), image_to_str(draw->info->fill_pattern));
602
+ rb_hash_aset(ddraw, CSTR2SYM("tile"), Qnil); // deprecated
603
+ rb_hash_aset(ddraw, CSTR2SYM("stroke_pattern"), image_to_str(draw->info->stroke_pattern));
604
+ rb_hash_aset(ddraw, CSTR2SYM("stroke_antialias"), draw->info->stroke_antialias ? Qtrue : Qfalse);
605
+ rb_hash_aset(ddraw, CSTR2SYM("text_antialias"), draw->info->text_antialias ? Qtrue : Qfalse);
606
+ // rb_hash_aset(ddraw, CSTR2SYM("fill_rule"), INT2FIX(draw->info->fill_rule)); internal
607
+ // rb_hash_aset(ddraw, CSTR2SYM("linecap"), INT2FIX(draw->info->linecap));
608
+ // rb_hash_aset(ddraw, CSTR2SYM("linejoin"), INT2FIX(draw->info->linejoin));
609
+ // rb_hash_aset(ddraw, CSTR2SYM("miterlimit"), ULONG2NUM(draw->info->miterlimit));
610
+ // rb_hash_aset(ddraw, CSTR2SYM("dash_offset"), rb_float_new(draw->info->dash_offset));
611
+ rb_hash_aset(ddraw, CSTR2SYM("decorate"), INT2FIX(draw->info->decorate));
612
+ // rb_hash_aset(ddraw, CSTR2SYM("compose"), INT2FIX(draw->info->compose)); set via "image" primitive
613
+ // rb_hash_aset(ddraw, CSTR2SYM("text"), MAGICK_STRING_TO_OBJ(draw->info->text)); set via "text" primitive
614
+ // rb_hash_aset(ddraw, CSTR2SYM("face"), Qnil); internal
615
+ rb_hash_aset(ddraw, CSTR2SYM("font"), MAGICK_STRING_TO_OBJ(draw->info->font));
616
+ // rb_hash_aset(ddraw, CSTR2SYM("metrics"), Qnil); internal
617
+ rb_hash_aset(ddraw, CSTR2SYM("family"), MAGICK_STRING_TO_OBJ(draw->info->family));
618
+ rb_hash_aset(ddraw, CSTR2SYM("style"), INT2FIX(draw->info->style));
619
+ rb_hash_aset(ddraw, CSTR2SYM("stretch"), INT2FIX(draw->info->stretch));
620
+ rb_hash_aset(ddraw, CSTR2SYM("weight"), ULONG2NUM(draw->info->weight));
621
+ rb_hash_aset(ddraw, CSTR2SYM("encoding"), MAGICK_STRING_TO_OBJ(draw->info->encoding));
622
+ rb_hash_aset(ddraw, CSTR2SYM("pointsize"), rb_float_new(draw->info->pointsize));
623
+ rb_hash_aset(ddraw, CSTR2SYM("density"), MAGICK_STRING_TO_OBJ(draw->info->density));
624
+ rb_hash_aset(ddraw, CSTR2SYM("align"), INT2FIX(draw->info->align));
625
+ rb_hash_aset(ddraw, CSTR2SYM("undercolor"), Pixel_from_PixelPacket(&draw->info->undercolor));
626
+ // rb_hash_aset(ddraw, CSTR2SYM("border_color"), Pixel_from_PixelPacket(&draw->info->border_color)); Montage and Polaroid
627
+ // rb_hash_aset(ddraw, CSTR2SYM("server_name"), MAGICK_STRING_TO_OBJ(draw->info->server_name));
628
+ // rb_hash_aset(ddraw, CSTR2SYM("dash_pattern"), dash_pattern_to_array(draw->info->dash_pattern)); internal
629
+ // rb_hash_aset(ddraw, CSTR2SYM("clip_mask"), MAGICK_STRING_TO_OBJ(draw->info->clip_mask)); internal
630
+ // rb_hash_aset(ddraw, CSTR2SYM("bounds"), Import_SegmentInfo(&draw->info->bounds)); internal
631
+ rb_hash_aset(ddraw, CSTR2SYM("clip_units"), INT2FIX(draw->info->clip_units));
632
+ rb_hash_aset(ddraw, CSTR2SYM("opacity"), QUANTUM2NUM(draw->info->opacity));
633
+ // rb_hash_aset(ddraw, CSTR2SYM("render"), draw->info->render ? Qtrue : Qfalse); internal
634
+ // rb_hash_aset(ddraw, CSTR2SYM("element_reference"), Qnil); // not used yet
635
+ // rb_hash_aset(ddraw, CSTR2SYM("debug"), draw->info->debug ? Qtrue : Qfalse);
636
+ #if defined(HAVE_ST_KERNING)
637
+ rb_hash_aset(ddraw, CSTR2SYM("kerning"), rb_float_new(draw->info->kerning));
638
+ #endif
639
+ #if defined(HAVE_ST_INTERWORD_SPACING)
640
+ rb_hash_aset(ddraw, CSTR2SYM("interword_spacing"), rb_float_new(draw->info->interword_spacing));
641
+ #endif
642
+
643
+ // Non-DrawInfo fields
644
+ rb_hash_aset(ddraw, CSTR2SYM("primitives"), draw->primitives);
645
+ // rb_hash_aset(ddraw, CSTR2SYM("shadow_color"), Pixel_from_PixelPacket(&draw->shadow_color)); Polaroid-only
646
+
647
+ return ddraw;
648
+ }
649
+
650
+
651
+ /**
652
+ * Support Marsal.load.
653
+ *
654
+ * Ruby usage:
655
+ * - @verbatim Draw#marshal_load @endverbatim
656
+ *
657
+ * Notes:
658
+ * - On entry all fields are all-bits-0
659
+ *
660
+ * @param self this object
661
+ * @param ddraw the marshalled object
662
+ * @return self, once marshalled
663
+ */
664
+ VALUE
665
+ Draw_marshal_load(VALUE self, VALUE ddraw)
666
+ {
667
+ Draw *draw;
668
+ Pixel *pixel;
669
+ VALUE val;
670
+
671
+ Data_Get_Struct(self, Draw, draw);
672
+
673
+ draw->info = magick_malloc(sizeof(DrawInfo));
674
+ if (!draw->info)
675
+ {
676
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
677
+ }
678
+ GetDrawInfo(NULL, draw->info);
679
+
680
+ OBJ_TO_MAGICK_STRING(draw->info->geometry, rb_hash_aref(ddraw, CSTR2SYM("geometry")));
681
+
682
+ //val = rb_hash_aref(ddraw, CSTR2SYM("viewbox"));
683
+ //Export_RectangleInfo(&draw->info->viewbox, val);
684
+
685
+ val = rb_hash_aref(ddraw, CSTR2SYM("affine"));
686
+ Export_AffineMatrix(&draw->info->affine, val);
687
+
688
+ draw->info->gravity = (GravityType) FIX2INT(rb_hash_aref(ddraw, CSTR2SYM("gravity")));
689
+
690
+ val = rb_hash_aref(ddraw, CSTR2SYM("fill"));
691
+ Data_Get_Struct(val, Pixel, pixel);
692
+ draw->info->fill = *pixel;
693
+
694
+ val = rb_hash_aref(ddraw, CSTR2SYM("stroke"));
695
+ Data_Get_Struct(val, Pixel, pixel);
696
+ draw->info->stroke = *pixel;
697
+
698
+ draw->info->stroke_width = NUM2DBL(rb_hash_aref(ddraw, CSTR2SYM("stroke_width")));
699
+ draw->info->fill_pattern = str_to_image(rb_hash_aref(ddraw, CSTR2SYM("fill_pattern")));
700
+ draw->info->stroke_pattern = str_to_image(rb_hash_aref(ddraw, CSTR2SYM("stroke_pattern")));
701
+ draw->info->stroke_antialias = RTEST(rb_hash_aref(ddraw, CSTR2SYM("stroke_antialias")));
702
+ draw->info->text_antialias = RTEST(rb_hash_aref(ddraw, CSTR2SYM("text_antialias")));
703
+ draw->info->decorate = (DecorationType) FIX2INT(rb_hash_aref(ddraw, CSTR2SYM("decorate")));
704
+ OBJ_TO_MAGICK_STRING(draw->info->font, rb_hash_aref(ddraw, CSTR2SYM("font")));
705
+ OBJ_TO_MAGICK_STRING(draw->info->family, rb_hash_aref(ddraw, CSTR2SYM("family")));
706
+
707
+ draw->info->style = (StyleType) FIX2INT(rb_hash_aref(ddraw, CSTR2SYM("style")));
708
+ draw->info->stretch = (StretchType) FIX2INT(rb_hash_aref(ddraw, CSTR2SYM("stretch")));
709
+ draw->info->weight = NUM2ULONG(rb_hash_aref(ddraw, CSTR2SYM("weight")));
710
+ OBJ_TO_MAGICK_STRING(draw->info->encoding, rb_hash_aref(ddraw, CSTR2SYM("encoding")));
711
+ draw->info->pointsize = NUM2DBL(rb_hash_aref(ddraw, CSTR2SYM("pointsize")));
712
+ OBJ_TO_MAGICK_STRING(draw->info->density, rb_hash_aref(ddraw, CSTR2SYM("density")));
713
+ draw->info->align = (AlignType) FIX2INT(rb_hash_aref(ddraw, CSTR2SYM("align")));
714
+
715
+ val = rb_hash_aref(ddraw, CSTR2SYM("undercolor"));
716
+ Data_Get_Struct(val, Pixel, pixel);
717
+ draw->info->undercolor = *pixel;
718
+
719
+ draw->info->clip_units = FIX2INT(rb_hash_aref(ddraw, CSTR2SYM("clip_units")));
720
+ draw->info->opacity = NUM2QUANTUM(rb_hash_aref(ddraw, CSTR2SYM("opacity")));
721
+ #if defined(HAVE_ST_KERNING)
722
+ draw->info->kerning = NUM2DBL(rb_hash_aref(ddraw, CSTR2SYM("kerning")));
723
+ #endif
724
+ #if defined(HAVE_ST_INTERWORD_SPACING)
725
+ draw->info->interword_spacing = NUM2DBL(rb_hash_aref(ddraw, CSTR2SYM("interword_spacing")));
726
+ #endif
727
+
728
+ draw->primitives = rb_hash_aref(ddraw, CSTR2SYM("primitives"));
729
+
730
+ RB_GC_GUARD(val);
731
+
732
+ return self;
733
+ }
734
+
735
+
736
+ /**
737
+ * Pointsize attribute writer.
738
+ *
739
+ * Ruby usage:
740
+ * - @verbatim Draw#pointsize= @endverbatim
741
+ *
742
+ * @param self this object
743
+ * @param pointsize the pointsize
744
+ * @return self
745
+ */
746
+ VALUE
747
+ Draw_pointsize_eq(VALUE self, VALUE pointsize)
748
+ {
749
+ Draw *draw;
750
+
751
+ rb_check_frozen(self);
752
+ Data_Get_Struct(self, Draw, draw);
753
+ draw->info->pointsize = NUM2DBL(pointsize);
754
+ return self;
755
+ }
756
+
757
+
758
+ /**
759
+ * Set rotation attribute value.
760
+ *
761
+ * Ruby usage:
762
+ * - @verbatim Magick::Draw#rotation= @endverbatim
763
+ *
764
+ * Notes:
765
+ * - Argument should be in degrees
766
+ * - Taken from Magick++'s Magick::Image::annotate method.
767
+ * Copyright Bob Friesenhahn, 1999, 2000, 2001, 2002
768
+ *
769
+ * @param self this object
770
+ * @param deg the number of degrees
771
+ * @return self
772
+ */
773
+ VALUE
774
+ Draw_rotation_eq(VALUE self, VALUE deg)
775
+ {
776
+ Draw *draw;
777
+ double degrees;
778
+ AffineMatrix affine, current;
779
+
780
+ rb_check_frozen(self);
781
+ Data_Get_Struct(self, Draw, draw);
782
+
783
+ degrees = NUM2DBL(deg);
784
+ if (fabs(degrees) > DBL_EPSILON)
785
+ {
786
+ affine.sx=1.0;
787
+ affine.rx=0.0;
788
+ affine.ry=0.0;
789
+ affine.sy=1.0;
790
+ affine.tx=0.0;
791
+ affine.ty=0.0;
792
+
793
+ current = draw->info->affine;
794
+ affine.sx=cos(DegreesToRadians(fmod(degrees,360.0)));
795
+ affine.rx=sin(DegreesToRadians(fmod(degrees,360.0)));
796
+ affine.ry=(-sin(DegreesToRadians(fmod(degrees,360.0))));
797
+ affine.sy=cos(DegreesToRadians(fmod(degrees,360.0)));
798
+
799
+ draw->info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
800
+ draw->info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
801
+ draw->info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
802
+ draw->info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
803
+ draw->info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
804
+ }
805
+
806
+ return self;
807
+ }
808
+
809
+
810
+ /**
811
+ * Stroke attribute writer.
812
+ *
813
+ * Ruby usage:
814
+ * - @verbatim Draw#stroke= @endverbatim
815
+ *
816
+ * @param self this object
817
+ * @param stroke the stroke
818
+ * @return self
819
+ */
820
+ VALUE
821
+ Draw_stroke_eq(VALUE self, VALUE stroke)
822
+ {
823
+ Draw *draw;
824
+
825
+ rb_check_frozen(self);
826
+ Data_Get_Struct(self, Draw, draw);
827
+ Color_to_PixelPacket(&draw->info->stroke, stroke);
828
+ return self;
829
+ }
830
+
831
+
832
+ /**
833
+ * Accept an image as a stroke pattern.
834
+ *
835
+ * Ruby usage:
836
+ * - @verbatim Draw#stroke_pattern= @endverbatim
837
+ *
838
+ * @param self this object
839
+ * @param pattern the pattern
840
+ * @return self
841
+ * @see Draw_fill_pattern_eq
842
+ */
843
+ VALUE
844
+ Draw_stroke_pattern_eq(VALUE self, VALUE pattern)
845
+ {
846
+ Draw *draw;
847
+ Image *image;
848
+
849
+ rb_check_frozen(self);
850
+ Data_Get_Struct(self, Draw, draw);
851
+
852
+ if (draw->info->stroke_pattern != NULL)
853
+ {
854
+ // Do not trace destruction
855
+ DestroyImage(draw->info->stroke_pattern);
856
+ draw->info->stroke_pattern = NULL;
857
+ }
858
+
859
+ if (!NIL_P(pattern))
860
+ {
861
+ // DestroyDrawInfo destroys the clone
862
+ pattern = rm_cur_image(pattern);
863
+ image = rm_check_destroyed(pattern);
864
+ // Do not trace creation
865
+ draw->info->stroke_pattern = rm_clone_image(image);
866
+ }
867
+
868
+ return self;
869
+ }
870
+
871
+
872
+ /**
873
+ * Stroke_width attribute writer.
874
+ *
875
+ * Ruby usage:
876
+ * - @verbatim Draw#stroke_width= @endverbatim
877
+ *
878
+ * @param self this object
879
+ * @param stroke_width the stroke_width
880
+ * @return self
881
+ */
882
+ VALUE
883
+ Draw_stroke_width_eq(VALUE self, VALUE stroke_width)
884
+ {
885
+ Draw *draw;
886
+
887
+ rb_check_frozen(self);
888
+ Data_Get_Struct(self, Draw, draw);
889
+ draw->info->stroke_width = NUM2DBL(stroke_width);
890
+ return self;
891
+ }
892
+
893
+
894
+ /**
895
+ * Text_antialias attribute writer.
896
+ *
897
+ * Ruby usage:
898
+ * - @verbatim Draw#text_antialias= @endverbatim
899
+ *
900
+ * @param self this object
901
+ * @param text_antialias the text_antialias
902
+ * @return self
903
+ */
904
+ VALUE
905
+ Draw_text_antialias_eq(VALUE self, VALUE text_antialias)
906
+ {
907
+ Draw *draw;
908
+
909
+ rb_check_frozen(self);
910
+ Data_Get_Struct(self, Draw, draw);
911
+ draw->info->text_antialias = (MagickBooleanType) RTEST(text_antialias);
912
+ return self;
913
+ }
914
+
915
+
916
+ /**
917
+ * Tile attribute writer.
918
+ *
919
+ * Ruby usage:
920
+ * - @verbatim Draw#tile= @endverbatim
921
+ *
922
+ * @param self this object
923
+ * @param image the image to tile
924
+ * @return self
925
+ */
926
+ VALUE
927
+ Draw_tile_eq(VALUE self, VALUE image)
928
+ {
929
+ return Draw_fill_pattern_eq(self, image);
930
+ }
931
+
932
+
933
+ /**
934
+ * Undercolor attribute writer.
935
+ *
936
+ * Ruby usage:
937
+ * - @verbatim Draw#undercolor= @endverbatim
938
+ *
939
+ * @param self this object
940
+ * @param undercolor the undercolor
941
+ * @return self
942
+ */
943
+ VALUE
944
+ Draw_undercolor_eq(VALUE self, VALUE undercolor)
945
+ {
946
+ Draw *draw;
947
+
948
+ rb_check_frozen(self);
949
+ Data_Get_Struct(self, Draw, draw);
950
+ Color_to_PixelPacket(&draw->info->undercolor, undercolor);
951
+ return self;
952
+ }
953
+
954
+
955
+ /**
956
+ * Annotates an image with text.
957
+ *
958
+ * Ruby usage:
959
+ * - @verbatim Draw#annotate(img, w, h, x, y, text) <{optional parms}> @endverbatim
960
+ *
961
+ * Notes:
962
+ * - Additional Draw attribute methods may be called in the optional block,
963
+ * which is executed in the context of an Draw object.
964
+ *
965
+ * @param self this object
966
+ * @param image_arg the image
967
+ * @param width_arg the width
968
+ * @param height_arg the height
969
+ * @param x_arg x position
970
+ * @param y_arg y position
971
+ * @param text the annotation text
972
+ * @return self
973
+ */
974
+ VALUE Draw_annotate(
975
+ VALUE self,
976
+ VALUE image_arg,
977
+ VALUE width_arg,
978
+ VALUE height_arg,
979
+ VALUE x_arg,
980
+ VALUE y_arg,
981
+ VALUE text)
982
+ {
983
+ Draw *draw;
984
+ Image *image;
985
+ unsigned long width, height;
986
+ long x, y;
987
+ AffineMatrix keep;
988
+ char geometry_str[50];
989
+
990
+ // Save the affine matrix in case it is modified by
991
+ // Draw#rotation=
992
+ Data_Get_Struct(self, Draw, draw);
993
+ keep = draw->info->affine;
994
+
995
+ image_arg = rm_cur_image(image_arg);
996
+ image = rm_check_frozen(image_arg);
997
+
998
+ // If we have an optional parm block, run it in self's context,
999
+ // allowing the app a chance to modify the object's attributes
1000
+ if (rb_block_given_p())
1001
+ {
1002
+ (void)rb_obj_instance_eval(0, NULL, self);
1003
+ }
1004
+
1005
+ // Translate & store in Draw structure
1006
+ draw->info->text = InterpretImageProperties(NULL, image, StringValuePtr(text));
1007
+ if (!draw->info->text)
1008
+ {
1009
+ rb_raise(rb_eArgError, "no text");
1010
+ }
1011
+
1012
+ // Create geometry string, copy to Draw structure, overriding
1013
+ // any previously existing value.
1014
+ width = NUM2ULONG(width_arg);
1015
+ height = NUM2ULONG(height_arg);
1016
+ x = NUM2LONG(x_arg);
1017
+ y = NUM2LONG(y_arg);
1018
+
1019
+ if (width == 0 && height == 0)
1020
+ {
1021
+ sprintf(geometry_str, "%+ld%+ld", x, y);
1022
+ }
1023
+
1024
+ // WxH is non-zero
1025
+ else
1026
+ {
1027
+ sprintf(geometry_str, "%lux%lu%+ld%+ld", width, height, x, y);
1028
+ }
1029
+
1030
+ magick_clone_string(&draw->info->geometry, geometry_str);
1031
+
1032
+ (void) AnnotateImage(image, draw->info);
1033
+
1034
+ magick_free(draw->info->text);
1035
+ draw->info->text = NULL;
1036
+ draw->info->affine = keep;
1037
+
1038
+ rm_check_image_exception(image, RetainOnError);
1039
+
1040
+ return self;
1041
+ }
1042
+
1043
+
1044
+ /**
1045
+ * Clones this object.
1046
+ *
1047
+ * Ruby usage:
1048
+ * - @verbatim Draw#clone @endverbatim
1049
+ *
1050
+ * @param self this object
1051
+ * @return the clone
1052
+ * @see Draw_dup
1053
+ * @see Draw_init_copy
1054
+ */
1055
+ VALUE
1056
+ Draw_clone(VALUE self)
1057
+ {
1058
+ VALUE clone;
1059
+
1060
+ clone = Draw_dup(self);
1061
+ if (OBJ_FROZEN(self))
1062
+ {
1063
+ OBJ_FREEZE(clone);
1064
+ }
1065
+
1066
+ RB_GC_GUARD(clone);
1067
+
1068
+ return clone;
1069
+ }
1070
+
1071
+
1072
+ /**
1073
+ * Implement the "image" drawing primitive.
1074
+ *
1075
+ * Ruby usage:
1076
+ * - @verbatim Draw#composite(x,y,width,height,img) @endverbatim
1077
+ * - @verbatim Draw#composite(x,y,width,height,img,operator) @endverbatim
1078
+ *
1079
+ * Notes:
1080
+ * - Default operator is overComposite
1081
+ * - The "img" argument can be either an ImageList object or an Image
1082
+ * argument.
1083
+ *
1084
+ * @param argc number of input arguments
1085
+ * @param argv array of input arguments
1086
+ * @param self this object
1087
+ * @return self
1088
+ */
1089
+ VALUE
1090
+ Draw_composite(int argc, VALUE *argv, VALUE self)
1091
+ {
1092
+ Draw *draw;
1093
+ const char *op = "Over";
1094
+ double x, y, width, height;
1095
+ CompositeOperator cop = OverCompositeOp;
1096
+ VALUE image;
1097
+ Image *comp_img;
1098
+ struct TmpFile_Name *tmpfile_name;
1099
+ char name[MaxTextExtent];
1100
+ // Buffer for "image" primitive
1101
+ char primitive[MaxTextExtent];
1102
+
1103
+ if (argc < 5 || argc > 6)
1104
+ {
1105
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 5 or 6)", argc);
1106
+ }
1107
+
1108
+ // Retrieve the image to composite
1109
+ image = rm_cur_image(argv[4]);
1110
+ (void) rm_check_destroyed(image);
1111
+
1112
+ x = NUM2DBL(argv[0]);
1113
+ y = NUM2DBL(argv[1]);
1114
+ width = NUM2DBL(argv[2]);
1115
+ height = NUM2DBL(argv[3]);
1116
+
1117
+ // The default composition operator is "Over".
1118
+ if (argc == 6)
1119
+ {
1120
+ VALUE_TO_ENUM(argv[5], cop, CompositeOperator);
1121
+
1122
+ switch (cop)
1123
+ {
1124
+ case AddCompositeOp:
1125
+ op = "Add";
1126
+ break;
1127
+ case AtopCompositeOp:
1128
+ op = "Atop";
1129
+ break;
1130
+ case BlendCompositeOp:
1131
+ op = "Blend";
1132
+ break;
1133
+ #if defined(HAVE_ENUM_BLURCOMPOSITEOP)
1134
+ case BlurCompositeOp:
1135
+ op = "Blur";
1136
+ break;
1137
+ #endif
1138
+ case BumpmapCompositeOp:
1139
+ op = "Bumpmap";
1140
+ break;
1141
+ case ChangeMaskCompositeOp:
1142
+ op = "ChangeMask";
1143
+ break;
1144
+ case ClearCompositeOp:
1145
+ op = "Clear";
1146
+ break;
1147
+ case ColorBurnCompositeOp:
1148
+ op = "ColorBurn";
1149
+ break;
1150
+ case ColorDodgeCompositeOp:
1151
+ op = "ColorDodge";
1152
+ break;
1153
+ case ColorizeCompositeOp:
1154
+ op = "Colorize";
1155
+ break;
1156
+ case CopyCompositeOp:
1157
+ op = "Copy";
1158
+ break;
1159
+ case CopyBlackCompositeOp:
1160
+ op = "CopyBlack";
1161
+ break;
1162
+ case CopyBlueCompositeOp:
1163
+ op = "CopyBlue";
1164
+ break;
1165
+ case CopyCyanCompositeOp:
1166
+ op = "CopyCyan";
1167
+ break;
1168
+ case CopyGreenCompositeOp:
1169
+ op = "CopyGreen";
1170
+ break;
1171
+ case CopyMagentaCompositeOp:
1172
+ op = "CopyMagenta";
1173
+ break;
1174
+ case CopyOpacityCompositeOp:
1175
+ op = "CopyOpacity";
1176
+ break;
1177
+ case CopyRedCompositeOp:
1178
+ op = "CopyRed";
1179
+ break;
1180
+ case CopyYellowCompositeOp:
1181
+ op = "CopyYellow";
1182
+ break;
1183
+ case DarkenCompositeOp:
1184
+ op = "Darken";
1185
+ break;
1186
+ #if defined(HAVE_ENUM_DISTORTCOMPOSITEOP)
1187
+ case DistortCompositeOp:
1188
+ op = "Distort";
1189
+ break;
1190
+ #endif
1191
+ case DivideCompositeOp:
1192
+ op = "Divide";
1193
+ break;
1194
+ case DstCompositeOp:
1195
+ op = "Dst";
1196
+ break;
1197
+ case DstAtopCompositeOp:
1198
+ op = "DstAtop";
1199
+ break;
1200
+ case DstInCompositeOp:
1201
+ op = "DstIn";
1202
+ break;
1203
+ case DstOutCompositeOp:
1204
+ op = "DstOut";
1205
+ break;
1206
+ case DstOverCompositeOp:
1207
+ op = "DstOver";
1208
+ break;
1209
+ case DifferenceCompositeOp:
1210
+ op = "Difference";
1211
+ break;
1212
+ case DisplaceCompositeOp:
1213
+ op = "Displace";
1214
+ break;
1215
+ case DissolveCompositeOp:
1216
+ op = "Dissolve";
1217
+ break;
1218
+ case ExclusionCompositeOp:
1219
+ op = "Exclusion";
1220
+ break;
1221
+ case HardLightCompositeOp:
1222
+ op = "HardLight";
1223
+ break;
1224
+ case HueCompositeOp:
1225
+ op = "Hue";
1226
+ break;
1227
+ case InCompositeOp:
1228
+ op = "In";
1229
+ break;
1230
+ case LightenCompositeOp:
1231
+ op = "Lighten";
1232
+ break;
1233
+ #if defined(HAVE_ENUM_LINEARBURNCOMPOSITEOP)
1234
+ case LinearBurnCompositeOp:
1235
+ op = "LinearBurn";
1236
+ break;
1237
+ #endif
1238
+ #if defined(HAVE_ENUM_LINEARDODGECOMPOSITEOP)
1239
+ case LinearDodgeCompositeOp:
1240
+ op = "LinearDodge";
1241
+ break;
1242
+ #endif
1243
+ case LinearLightCompositeOp:
1244
+ op = "LinearLight";
1245
+ break;
1246
+ case LuminizeCompositeOp:
1247
+ op = "Luminize";
1248
+ break;
1249
+ case MinusCompositeOp:
1250
+ op = "Minus";
1251
+ break;
1252
+ case ModulateCompositeOp:
1253
+ op = "Modulate";
1254
+ break;
1255
+ case MultiplyCompositeOp:
1256
+ op = "Multiply";
1257
+ break;
1258
+ case OutCompositeOp:
1259
+ op = "Out";
1260
+ break;
1261
+ case OverCompositeOp:
1262
+ op = "Over";
1263
+ break;
1264
+ case OverlayCompositeOp:
1265
+ op = "Overlay";
1266
+ break;
1267
+ #if defined(HAVE_ENUM_PEGTOPLIGHTCOMPOSITEOP)
1268
+ case PegtopLightCompositeOp:
1269
+ op = "PegtopLight";
1270
+ break;
1271
+ #endif
1272
+ #if defined(HAVE_ENUM_PINLIGHTCOMPOSITEOP)
1273
+ case PinLightCompositeOp:
1274
+ op = "PinLight";
1275
+ break;
1276
+ #endif
1277
+ case PlusCompositeOp:
1278
+ op = "Plus";
1279
+ break;
1280
+ case ReplaceCompositeOp:
1281
+ op = "Replace";
1282
+ break;
1283
+ case SaturateCompositeOp:
1284
+ op = "Saturate";
1285
+ break;
1286
+ case ScreenCompositeOp:
1287
+ op = "Screen";
1288
+ break;
1289
+ case SoftLightCompositeOp:
1290
+ op = "SoftLight";
1291
+ break;
1292
+ case SrcCompositeOp:
1293
+ op = "Src";
1294
+ break;
1295
+ case SrcAtopCompositeOp:
1296
+ op = "SrcAtop";
1297
+ break;
1298
+ case SrcInCompositeOp:
1299
+ op = "SrcIn";
1300
+ break;
1301
+ case SrcOutCompositeOp:
1302
+ op = "SrcOut";
1303
+ break;
1304
+ case SrcOverCompositeOp:
1305
+ op = "SrcOver";
1306
+ break;
1307
+ case SubtractCompositeOp:
1308
+ op = "Subtract";
1309
+ break;
1310
+ case ThresholdCompositeOp:
1311
+ op = "Threshold";
1312
+ break;
1313
+ #if defined(HAVE_ENUM_VIVIDLIGHTCOMPOSITEOP)
1314
+ case VividLightCompositeOp:
1315
+ op = "VividLight";
1316
+ break;
1317
+ #endif
1318
+ case XorCompositeOp:
1319
+ op = "Xor";
1320
+ break;
1321
+ default:
1322
+ rb_raise(rb_eArgError, "unknown composite operator (%d)", cop);
1323
+ break;
1324
+ }
1325
+ }
1326
+
1327
+ Data_Get_Struct(self, Draw, draw);
1328
+
1329
+ // Create a temp copy of the composite image
1330
+ Data_Get_Struct(image, Image, comp_img);
1331
+ rm_write_temp_image(comp_img, name);
1332
+
1333
+ // Add the temp filename to the filename array.
1334
+ // Use Magick storage since we need to keep the list around
1335
+ // until destroy_Draw is called.
1336
+ tmpfile_name = magick_malloc(sizeof(struct TmpFile_Name)+strlen(name));
1337
+ strcpy(tmpfile_name->name, name);
1338
+ tmpfile_name->next = draw->tmpfile_ary;
1339
+ draw->tmpfile_ary = tmpfile_name;
1340
+
1341
+ // Form the drawing primitive
1342
+ (void) sprintf(primitive, "image %s %g,%g,%g,%g '%s'", op, x, y, width, height, name);
1343
+
1344
+
1345
+ // Send "primitive" to self.
1346
+ (void) rb_funcall(self, rb_intern("primitive"), 1, rb_str_new2(primitive));
1347
+
1348
+ RB_GC_GUARD(image);
1349
+
1350
+ return self;
1351
+ }
1352
+
1353
+
1354
+ /**
1355
+ * Execute the stored drawing primitives on the current image.
1356
+ *
1357
+ * Ruby usage:
1358
+ * - @verbatim Draw#draw(i) @endverbatim
1359
+ *
1360
+ * @param self this object
1361
+ * @param image_arg the image argument
1362
+ * @return self
1363
+ */
1364
+ VALUE
1365
+ Draw_draw(VALUE self, VALUE image_arg)
1366
+ {
1367
+ Draw *draw;
1368
+ Image *image;
1369
+
1370
+ image_arg = rm_cur_image(image_arg);
1371
+ image = rm_check_frozen(image_arg);
1372
+
1373
+ Data_Get_Struct(self, Draw, draw);
1374
+ if (draw->primitives == 0)
1375
+ {
1376
+ rb_raise(rb_eArgError, "nothing to draw");
1377
+ }
1378
+
1379
+ // Point the DrawInfo structure at the current set of primitives.
1380
+ magick_clone_string(&(draw->info->primitive), StringValuePtr(draw->primitives));
1381
+
1382
+ (void) DrawImage(image, draw->info);
1383
+ rm_check_image_exception(image, RetainOnError);
1384
+
1385
+ magick_free(draw->info->primitive);
1386
+ draw->info->primitive = NULL;
1387
+
1388
+ return self;
1389
+ }
1390
+
1391
+
1392
+ /**
1393
+ * Copy a Draw object.
1394
+ *
1395
+ * Ruby usage:
1396
+ * - @verbatim Draw#dup @endverbatim
1397
+ *
1398
+ * Notes:
1399
+ * - Constructs a new Draw object, then calls initialize_copy.
1400
+ *
1401
+ * @param self this object
1402
+ * @return the duplicate
1403
+ * @see Draw_clone
1404
+ * @see Draw_init_copy
1405
+ */
1406
+ VALUE
1407
+ Draw_dup(VALUE self)
1408
+ {
1409
+ Draw *draw;
1410
+ VALUE dup;
1411
+
1412
+ draw = ALLOC(Draw);
1413
+ memset(draw, 0, sizeof(Draw));
1414
+ dup = Data_Wrap_Struct(CLASS_OF(self), mark_Draw, destroy_Draw, draw);
1415
+ if (rb_obj_tainted(self))
1416
+ {
1417
+ (void)rb_obj_taint(dup);
1418
+ }
1419
+
1420
+ RB_GC_GUARD(dup);
1421
+
1422
+ return rb_funcall(dup, rm_ID_initialize_copy, 1, self);
1423
+ }
1424
+
1425
+
1426
+ /**
1427
+ * Returns measurements for a given font and text string.
1428
+ *
1429
+ * Ruby usage:
1430
+ * - @verbatim Draw#get_type_metrics(text) @endverbatim
1431
+ * - @verbatim Draw#get_type_metrics(image, text) @endverbatim
1432
+ *
1433
+ * Notes:
1434
+ * - If the image argument has been omitted, use a dummy image, but make sure
1435
+ * the text has none of the special characters that refer to image
1436
+ * attributes.
1437
+ *
1438
+ * @param argc number of input arguments
1439
+ * @param argv array of input arguments
1440
+ * @param self this object
1441
+ * @return the duplicate
1442
+ */
1443
+ VALUE
1444
+ Draw_get_type_metrics(
1445
+ int argc,
1446
+ VALUE *argv,
1447
+ VALUE self)
1448
+ {
1449
+ return get_type_metrics(argc, argv, self, GetTypeMetrics);
1450
+ }
1451
+
1452
+
1453
+ /**
1454
+ * Returns measurements for a given font and text string.
1455
+ *
1456
+ * Ruby usage:
1457
+ * - @verbatim Draw#get_multiline_type_metrics(text) @endverbatim
1458
+ * - @verbatim Draw#get_multiline_type_metrics(image, text) @endverbatim
1459
+ *
1460
+ * Notes:
1461
+ * - If the image argument has been omitted, use a dummy image, but make sure
1462
+ * the text has none of the special characters that refer to image
1463
+ * attributes.
1464
+ *
1465
+ * @param argc number of input arguments
1466
+ * @param argv array of input arguments
1467
+ * @param self this object
1468
+ * @return the duplicate
1469
+ */
1470
+ VALUE
1471
+ Draw_get_multiline_type_metrics(
1472
+ int argc,
1473
+ VALUE *argv,
1474
+ VALUE self)
1475
+ {
1476
+ return get_type_metrics(argc, argv, self, GetMultilineTypeMetrics);
1477
+ }
1478
+
1479
+
1480
+ /**
1481
+ * Initialize clone, dup methods.
1482
+ *
1483
+ * Ruby usage:
1484
+ * - @verbatim Draw#initialize_copy @endverbatim
1485
+ *
1486
+ * @param self this object
1487
+ * @param orig the original object
1488
+ * @return self
1489
+ * @see Draw_clone
1490
+ * @see Draw_dup
1491
+ */
1492
+ VALUE Draw_init_copy(VALUE self, VALUE orig)
1493
+ {
1494
+ Draw *copy, *original;
1495
+
1496
+ Data_Get_Struct(orig, Draw, original);
1497
+ Data_Get_Struct(self, Draw, copy);
1498
+
1499
+ copy->info = CloneDrawInfo(NULL, original->info);
1500
+ if (!copy->info)
1501
+ {
1502
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
1503
+ }
1504
+
1505
+ if (original->primitives)
1506
+ {
1507
+ copy->primitives = rb_str_dup(original->primitives);
1508
+ }
1509
+
1510
+ return self;
1511
+ }
1512
+
1513
+
1514
+ /**
1515
+ * Initialize Draw object.
1516
+ *
1517
+ * Ruby usage:
1518
+ * - @verbatim Draw#initialize <{ info initializers }> @endverbatim
1519
+ *
1520
+ * @param self this object
1521
+ * @return self
1522
+ */
1523
+ VALUE
1524
+ Draw_initialize(VALUE self)
1525
+ {
1526
+ Draw *draw, *draw_options;
1527
+ VALUE options;
1528
+
1529
+ Data_Get_Struct(self, Draw, draw);
1530
+
1531
+ options = new_DrawOptions();
1532
+ Data_Get_Struct(options, Draw, draw_options);
1533
+ draw->info = draw_options->info;
1534
+ draw_options->info = NULL;
1535
+
1536
+ RB_GC_GUARD(options);
1537
+
1538
+ return self;
1539
+ }
1540
+
1541
+
1542
+ /**
1543
+ * Display the primitives.
1544
+ *
1545
+ * Ruby usage:
1546
+ * - @verbatim Draw#inspect @endverbatim
1547
+ *
1548
+ * @param self this object
1549
+ * @return the draw primitives or the Ruby string "(no primitives defined)" if
1550
+ * they are not defined
1551
+ */
1552
+ VALUE
1553
+ Draw_inspect(VALUE self)
1554
+ {
1555
+ Draw *draw;
1556
+
1557
+ Data_Get_Struct(self, Draw, draw);
1558
+ return draw->primitives ? draw->primitives : rb_str_new2("(no primitives defined)");
1559
+ }
1560
+
1561
+
1562
+ /**
1563
+ * Create a new Draw object.
1564
+ *
1565
+ * Ruby usage:
1566
+ * - @verbatim Draw.new @endverbatim
1567
+ * - @verbatim Draw.allocate @endverbatim
1568
+ *
1569
+ * @param class the Ruby Draw class
1570
+ * @return a new Draw object
1571
+ * @throw ImageMagickError if no memory
1572
+ */
1573
+ VALUE Draw_alloc(VALUE class)
1574
+ {
1575
+ Draw *draw;
1576
+ VALUE draw_obj;
1577
+
1578
+ draw = ALLOC(Draw);
1579
+ memset(draw, 0, sizeof(Draw));
1580
+ draw_obj = Data_Wrap_Struct(class, mark_Draw, destroy_Draw, draw);
1581
+
1582
+ RB_GC_GUARD(draw_obj);
1583
+
1584
+ return draw_obj;
1585
+ }
1586
+
1587
+
1588
+ /**
1589
+ * Add a drawing primitive to the list of primitives in the Draw object.
1590
+ *
1591
+ * Ruby usage:
1592
+ * - @verbatim Draw#primitive @endverbatim
1593
+ *
1594
+ * @param self this object
1595
+ * @param primitive the primitive to add
1596
+ * @return self
1597
+ */
1598
+ VALUE
1599
+ Draw_primitive(VALUE self, VALUE primitive)
1600
+ {
1601
+ Draw *draw;
1602
+
1603
+ rb_check_frozen(self);
1604
+ Data_Get_Struct(self, Draw, draw);
1605
+
1606
+ if (draw->primitives == (VALUE)0)
1607
+ {
1608
+ draw->primitives = primitive;
1609
+ }
1610
+ else
1611
+ {
1612
+ draw->primitives = rb_str_concat(draw->primitives, rb_str_new2("\n"));
1613
+ draw->primitives = rb_str_concat(draw->primitives, primitive);
1614
+ }
1615
+
1616
+ return self;
1617
+ }
1618
+
1619
+
1620
+ /**
1621
+ * Mark referenced objects.
1622
+ *
1623
+ * No Ruby usage (internal function)
1624
+ *
1625
+ * @param drawptr pointer to a Draw object
1626
+ */
1627
+ static void
1628
+ mark_Draw(void *drawptr)
1629
+ {
1630
+ Draw *draw = (Draw *)drawptr;
1631
+
1632
+ if (draw->primitives != (VALUE)0)
1633
+ {
1634
+ rb_gc_mark(draw->primitives);
1635
+ }
1636
+ }
1637
+
1638
+
1639
+ /**
1640
+ * Free the memory associated with an Draw object.
1641
+ *
1642
+ * No Ruby usage (internal function)
1643
+ *
1644
+ * @param drawptr pointer to a Draw object
1645
+ */
1646
+ static void
1647
+ destroy_Draw(void *drawptr)
1648
+ {
1649
+ Draw *draw = (Draw *)drawptr;
1650
+ struct TmpFile_Name *tmpfile_name;
1651
+
1652
+ if (draw->info)
1653
+ {
1654
+ (void) DestroyDrawInfo(draw->info);
1655
+ draw->info = NULL;
1656
+ }
1657
+
1658
+ // Erase any temporary image files.
1659
+ while (draw->tmpfile_ary)
1660
+ {
1661
+ tmpfile_name = draw->tmpfile_ary;
1662
+ draw->tmpfile_ary = draw->tmpfile_ary->next;
1663
+ rm_delete_temp_image(tmpfile_name->name);
1664
+ magick_free(tmpfile_name);
1665
+ }
1666
+
1667
+ xfree(drawptr);
1668
+ }
1669
+
1670
+
1671
+ /**
1672
+ * Allocate & initialize a DrawOptions object.
1673
+ *
1674
+ * No Ruby usage (internal function)
1675
+ *
1676
+ * @return a new DrawOptions object
1677
+ */
1678
+ static VALUE
1679
+ new_DrawOptions(void)
1680
+ {
1681
+ return DrawOptions_initialize(Draw_alloc(Class_DrawOptions));
1682
+ }
1683
+
1684
+
1685
+ /**
1686
+ * Create a DrawOptions object.
1687
+ *
1688
+ * Ruby usage:
1689
+ * - @verbatim DrawOptions#allocate @endverbatim
1690
+ * - @verbatim DrawOptions#new @endverbatim
1691
+ *
1692
+ * Notes:
1693
+ * - The DrawOptions class is the same as the Draw class except is has only
1694
+ * the attribute writer functions
1695
+ *
1696
+ * @param class the Ruby DrawOptions class
1697
+ * @return a new DrawOptions object
1698
+ */
1699
+ VALUE
1700
+ DrawOptions_alloc(VALUE class)
1701
+ {
1702
+ Draw *draw_options;
1703
+ VALUE draw_options_obj;
1704
+
1705
+ draw_options = ALLOC(Draw);
1706
+ memset(draw_options, 0, sizeof(Draw));
1707
+ draw_options_obj = Data_Wrap_Struct(class, mark_Draw, destroy_Draw, draw_options);
1708
+
1709
+ RB_GC_GUARD(draw_options_obj);
1710
+
1711
+ return draw_options_obj;
1712
+ }
1713
+
1714
+
1715
+ /**
1716
+ * Initialize a DrawOptions object.
1717
+ *
1718
+ * Ruby usage:
1719
+ * - @verbatim DrawOptions#initialize @endverbatim
1720
+ *
1721
+ * @param self this object
1722
+ * @return self
1723
+ */
1724
+ VALUE
1725
+ DrawOptions_initialize(VALUE self)
1726
+ {
1727
+ Draw *draw_options;
1728
+
1729
+ Data_Get_Struct(self, Draw, draw_options);
1730
+ draw_options->info = magick_malloc(sizeof(DrawInfo));
1731
+ if (!draw_options->info)
1732
+ {
1733
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
1734
+ }
1735
+
1736
+ GetDrawInfo(NULL, draw_options->info);
1737
+
1738
+ if (rb_block_given_p())
1739
+ {
1740
+ // Run the block in self's context
1741
+ (void) rb_obj_instance_eval(0, NULL, self);
1742
+ }
1743
+
1744
+ return self;
1745
+ }
1746
+
1747
+
1748
+ /**
1749
+ * Allocate a new Magick::PolaroidOptions object.
1750
+ *
1751
+ * Ruby usage:
1752
+ * - @verbatim Magick::PolaroidOptions#allocate @endverbatim
1753
+ * - @verbatim Magick::PolaroidOptions#new @endverbatim
1754
+ *
1755
+ * Notes:
1756
+ * - Internally a PolaroidOptions object is the same as a Draw object. The
1757
+ * methods are implemented by Draw methods in rmdraw.c.
1758
+ *
1759
+ * @param class the Ruby PoloradoidOptions class
1760
+ * @return a new DrawOptions object
1761
+ */
1762
+ VALUE
1763
+ PolaroidOptions_alloc(VALUE class)
1764
+ {
1765
+ VALUE polaroid_obj;
1766
+ ImageInfo *image_info;
1767
+ Draw *draw;
1768
+
1769
+ image_info = CloneImageInfo(NULL);
1770
+
1771
+ draw = ALLOC(Draw);
1772
+ memset(draw, 0, sizeof(*draw));
1773
+
1774
+ draw->info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
1775
+ (void)(void) DestroyImageInfo(image_info);
1776
+
1777
+ polaroid_obj = Data_Wrap_Struct(class, NULL, destroy_Draw, draw);
1778
+
1779
+ RB_GC_GUARD(polaroid_obj);
1780
+
1781
+ return polaroid_obj;
1782
+ }
1783
+
1784
+
1785
+ /**
1786
+ * Yield to an optional block.
1787
+ *
1788
+ * Ruby usage:
1789
+ * - @verbatim Magick::PolaroidOptions#initialize @endverbatim
1790
+ *
1791
+ * @param self this object
1792
+ * @return self
1793
+ */
1794
+ VALUE
1795
+ PolaroidOptions_initialize(VALUE self)
1796
+ {
1797
+ Draw *draw;
1798
+ ExceptionInfo *exception;
1799
+
1800
+ // Default shadow color
1801
+ Data_Get_Struct(self, Draw, draw);
1802
+
1803
+ exception = AcquireExceptionInfo();
1804
+ (void) QueryColorDatabase("gray75", &draw->shadow_color, exception);
1805
+ CHECK_EXCEPTION()
1806
+ (void) QueryColorDatabase("#dfdfdf", &draw->info->border_color, exception);
1807
+
1808
+ if (rb_block_given_p())
1809
+ {
1810
+ // Run the block in self's context
1811
+ (void) rb_obj_instance_eval(0, NULL, self);
1812
+ }
1813
+ return self;
1814
+ }
1815
+
1816
+
1817
+ /**
1818
+ * Allocate a PolaroidOptions instance.
1819
+ *
1820
+ * No Ruby usage (internal function)
1821
+ *
1822
+ * @return new PolaroidOptions object
1823
+ */
1824
+ VALUE
1825
+ rm_polaroid_new(void)
1826
+ {
1827
+ return PolaroidOptions_initialize(PolaroidOptions_alloc(Class_PolaroidOptions));
1828
+ }
1829
+
1830
+
1831
+ /**
1832
+ * Set the shadow color attribute.
1833
+ *
1834
+ * Ruby usage:
1835
+ * - @verbatim PolaroidOptions#shadow_color= @endverbatim
1836
+ *
1837
+ * @param self this object
1838
+ * @param shadow the shadow color
1839
+ * @return self
1840
+ */
1841
+ VALUE
1842
+ PolaroidOptions_shadow_color_eq(VALUE self, VALUE shadow)
1843
+ {
1844
+ Draw *draw;
1845
+
1846
+ Data_Get_Struct(self, Draw, draw);
1847
+ Color_to_PixelPacket(&draw->shadow_color, shadow);
1848
+ return self;
1849
+ }
1850
+
1851
+
1852
+ /**
1853
+ * Set the border color attribute.
1854
+ *
1855
+ * Ruby usage:
1856
+ * - @verbatim PolaroidOptions#border_color= @endverbatim
1857
+ *
1858
+ * @param self this object
1859
+ * @param border the border color
1860
+ * @return self
1861
+ */
1862
+ VALUE
1863
+ PolaroidOptions_border_color_eq(VALUE self, VALUE border)
1864
+ {
1865
+ Draw *draw;
1866
+
1867
+ Data_Get_Struct(self, Draw, draw);
1868
+ Color_to_PixelPacket(&draw->info->border_color, border);
1869
+ return self;
1870
+ }
1871
+
1872
+
1873
+ /**
1874
+ * Create a dummy object of an image class.
1875
+ *
1876
+ * No Ruby usage (internal function)
1877
+ *
1878
+ * @param klass the class for which to create a dummy
1879
+ * @return the newly allocated dummy
1880
+ */
1881
+ static VALUE
1882
+ get_dummy_tm_img(VALUE klass)
1883
+ {
1884
+ #define DUMMY_IMG_CLASS_VAR "@@_dummy_img_"
1885
+ VALUE dummy_img = 0;
1886
+ Info *info;
1887
+ Image *image;
1888
+
1889
+ if (rb_cvar_defined(klass, rb_intern(DUMMY_IMG_CLASS_VAR)) != Qtrue)
1890
+ {
1891
+
1892
+ info = CloneImageInfo(NULL);
1893
+ if (!info)
1894
+ {
1895
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
1896
+ }
1897
+ image = AcquireImage(info);
1898
+ if (!image)
1899
+ {
1900
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
1901
+ }
1902
+ (void) DestroyImageInfo(info);
1903
+ dummy_img = rm_image_new(image);
1904
+
1905
+ rb_cv_set(klass, DUMMY_IMG_CLASS_VAR, dummy_img);
1906
+ }
1907
+ dummy_img = rb_cv_get(klass, DUMMY_IMG_CLASS_VAR);
1908
+
1909
+ RB_GC_GUARD(dummy_img);
1910
+
1911
+ return dummy_img;
1912
+ }
1913
+
1914
+
1915
+ /**
1916
+ * Call a get-type-metrics function.
1917
+ *
1918
+ * No Ruby usage (internal function)
1919
+ *
1920
+ * Notes:
1921
+ * - called by Draw_get_type_metrics and Draw_get_multiline_type_metrics
1922
+ *
1923
+ * @param argc number of input arguments
1924
+ * @param argv array of input arguments
1925
+ * @param self this object
1926
+ * @param getter which type metrics to get
1927
+ * @return the type metrics
1928
+ * @see Draw_get_type_metrics
1929
+ * @see Draw_get_multiline_type_metrics
1930
+ */
1931
+ static VALUE
1932
+ get_type_metrics(
1933
+ int argc,
1934
+ VALUE *argv,
1935
+ VALUE self,
1936
+ get_type_metrics_func_t getter)
1937
+ {
1938
+ static char attrs[] = "OPbcdefghiklmnopqrstuwxyz[@#%";
1939
+ #define ATTRS_L ((int)(sizeof(attrs)-1))
1940
+ Image *image;
1941
+ Draw *draw;
1942
+ VALUE t;
1943
+ TypeMetric metrics;
1944
+ char *text = NULL;
1945
+ long text_l;
1946
+ long x;
1947
+ unsigned int okay;
1948
+
1949
+ switch (argc)
1950
+ {
1951
+ case 1: // use default image
1952
+ text = rm_str2cstr(argv[0], &text_l);
1953
+
1954
+ for (x = 0; x < text_l-1; x++)
1955
+ {
1956
+ // Ensure text string doesn't refer to image attributes.
1957
+ if (text[x] == '%')
1958
+ {
1959
+ int y;
1960
+ char spec = text[x+1];
1961
+
1962
+ if (spec == '%')
1963
+ {
1964
+ x++;
1965
+ }
1966
+ else
1967
+ {
1968
+ for (y = 0; y < ATTRS_L; y++)
1969
+ {
1970
+ if (spec == attrs[y])
1971
+ {
1972
+ rb_raise(rb_eArgError,
1973
+ "text string contains image attribute reference `%%%c'",
1974
+ spec);
1975
+ }
1976
+ }
1977
+ }
1978
+ }
1979
+ }
1980
+
1981
+ Data_Get_Struct(get_dummy_tm_img(CLASS_OF(self)), Image, image);
1982
+ break;
1983
+ case 2:
1984
+ t = rm_cur_image(argv[0]);
1985
+ image = rm_check_destroyed(t);
1986
+ text = rm_str2cstr(argv[1], &text_l);
1987
+ break; // okay
1988
+ default:
1989
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 2)", argc);
1990
+ break;
1991
+ }
1992
+
1993
+ if (text_l == 0)
1994
+ {
1995
+ rb_raise(rb_eArgError, "no text to measure");
1996
+ }
1997
+
1998
+ Data_Get_Struct(self, Draw, draw);
1999
+ draw->info->text = InterpretImageProperties(NULL, image, text);
2000
+ if (!draw->info->text)
2001
+ {
2002
+ rb_raise(rb_eArgError, "no text to measure");
2003
+ }
2004
+
2005
+ okay = (*getter)(image, draw->info, &metrics);
2006
+
2007
+ magick_free(draw->info->text);
2008
+ draw->info->text = NULL;
2009
+
2010
+ if (!okay)
2011
+ {
2012
+ rm_check_image_exception(image, RetainOnError);
2013
+
2014
+ // Shouldn't get here...
2015
+ rb_raise(rb_eRuntimeError, "Can't measure text. Are the fonts installed? "
2016
+ "Is the FreeType library installed?");
2017
+ }
2018
+
2019
+ RB_GC_GUARD(t);
2020
+
2021
+ return Import_TypeMetric(&metrics);
2022
+ }