rdp-rmagick 0.0.0

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