rmagick 1.7.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rmagick might be problematic. Click here for more details.

Files changed (239) hide show
  1. data/ChangeLog +232 -0
  2. data/Makefile.in +28 -0
  3. data/README.html +404 -0
  4. data/README.txt +397 -0
  5. data/configure +8554 -0
  6. data/configure.ac +497 -0
  7. data/doc/comtasks.html +241 -0
  8. data/doc/constants.html +1195 -0
  9. data/doc/css/doc.css +299 -0
  10. data/doc/css/popup.css +34 -0
  11. data/doc/draw.html +3108 -0
  12. data/doc/ex/Adispatch.rb +43 -0
  13. data/doc/ex/Zconstitute.rb +9 -0
  14. data/doc/ex/adaptive_threshold.rb +19 -0
  15. data/doc/ex/add_noise.rb +18 -0
  16. data/doc/ex/affine.rb +48 -0
  17. data/doc/ex/affine_transform.rb +20 -0
  18. data/doc/ex/arc.rb +47 -0
  19. data/doc/ex/arcpath.rb +33 -0
  20. data/doc/ex/average.rb +15 -0
  21. data/doc/ex/axes.rb +64 -0
  22. data/doc/ex/bilevel_channel.rb +20 -0
  23. data/doc/ex/blur_image.rb +12 -0
  24. data/doc/ex/border.rb +10 -0
  25. data/doc/ex/bounding_box.rb +48 -0
  26. data/doc/ex/cbezier1.rb +40 -0
  27. data/doc/ex/cbezier2.rb +40 -0
  28. data/doc/ex/cbezier3.rb +40 -0
  29. data/doc/ex/cbezier4.rb +41 -0
  30. data/doc/ex/cbezier5.rb +41 -0
  31. data/doc/ex/cbezier6.rb +51 -0
  32. data/doc/ex/channel.rb +26 -0
  33. data/doc/ex/channel_threshold.rb +48 -0
  34. data/doc/ex/charcoal.rb +12 -0
  35. data/doc/ex/chop.rb +29 -0
  36. data/doc/ex/circle.rb +31 -0
  37. data/doc/ex/clip_path.rb +56 -0
  38. data/doc/ex/coalesce.rb +60 -0
  39. data/doc/ex/color_fill_to_border.rb +29 -0
  40. data/doc/ex/color_floodfill.rb +28 -0
  41. data/doc/ex/color_histogram.rb +60 -0
  42. data/doc/ex/color_reset.rb +11 -0
  43. data/doc/ex/colorize.rb +16 -0
  44. data/doc/ex/colors.rb +65 -0
  45. data/doc/ex/composite.rb +135 -0
  46. data/doc/ex/contrast.rb +37 -0
  47. data/doc/ex/crop.rb +31 -0
  48. data/doc/ex/crop_with_gravity.rb +46 -0
  49. data/doc/ex/cycle_colormap.rb +21 -0
  50. data/doc/ex/demo.rb +324 -0
  51. data/doc/ex/drawcomp.rb +42 -0
  52. data/doc/ex/drop_shadow.rb +60 -0
  53. data/doc/ex/edge.rb +11 -0
  54. data/doc/ex/ellipse.rb +43 -0
  55. data/doc/ex/emboss.rb +11 -0
  56. data/doc/ex/enhance.rb +28 -0
  57. data/doc/ex/equalize.rb +11 -0
  58. data/doc/ex/flatten_images.rb +38 -0
  59. data/doc/ex/flip.rb +11 -0
  60. data/doc/ex/flop.rb +11 -0
  61. data/doc/ex/fonts.rb +20 -0
  62. data/doc/ex/frame.rb +12 -0
  63. data/doc/ex/gaussian_blur.rb +11 -0
  64. data/doc/ex/get_multiline_type_metrics.rb +53 -0
  65. data/doc/ex/get_pixels.rb +48 -0
  66. data/doc/ex/get_type_metrics.rb +140 -0
  67. data/doc/ex/gradientfill.rb +27 -0
  68. data/doc/ex/grav.rb +44 -0
  69. data/doc/ex/gravity.rb +80 -0
  70. data/doc/ex/hatchfill.rb +27 -0
  71. data/doc/ex/images/Ballerina.jpg +0 -0
  72. data/doc/ex/images/Ballerina3.jpg +0 -0
  73. data/doc/ex/images/Button_0.gif +0 -0
  74. data/doc/ex/images/Button_1.gif +0 -0
  75. data/doc/ex/images/Button_2.gif +0 -0
  76. data/doc/ex/images/Button_3.gif +0 -0
  77. data/doc/ex/images/Button_4.gif +0 -0
  78. data/doc/ex/images/Button_5.gif +0 -0
  79. data/doc/ex/images/Button_6.gif +0 -0
  80. data/doc/ex/images/Button_7.gif +0 -0
  81. data/doc/ex/images/Button_8.gif +0 -0
  82. data/doc/ex/images/Button_9.gif +0 -0
  83. data/doc/ex/images/Button_A.gif +0 -0
  84. data/doc/ex/images/Button_B.gif +0 -0
  85. data/doc/ex/images/Button_C.gif +0 -0
  86. data/doc/ex/images/Button_D.gif +0 -0
  87. data/doc/ex/images/Button_E.gif +0 -0
  88. data/doc/ex/images/Button_F.gif +0 -0
  89. data/doc/ex/images/Button_G.gif +0 -0
  90. data/doc/ex/images/Button_H.gif +0 -0
  91. data/doc/ex/images/Button_I.gif +0 -0
  92. data/doc/ex/images/Button_J.gif +0 -0
  93. data/doc/ex/images/Button_K.gif +0 -0
  94. data/doc/ex/images/Button_L.gif +0 -0
  95. data/doc/ex/images/Button_M.gif +0 -0
  96. data/doc/ex/images/Button_N.gif +0 -0
  97. data/doc/ex/images/Button_O.gif +0 -0
  98. data/doc/ex/images/Button_P.gif +0 -0
  99. data/doc/ex/images/Button_Q.gif +0 -0
  100. data/doc/ex/images/Button_R.gif +0 -0
  101. data/doc/ex/images/Button_S.gif +0 -0
  102. data/doc/ex/images/Button_T.gif +0 -0
  103. data/doc/ex/images/Button_U.gif +0 -0
  104. data/doc/ex/images/Button_V.gif +0 -0
  105. data/doc/ex/images/Button_W.gif +0 -0
  106. data/doc/ex/images/Button_X.gif +0 -0
  107. data/doc/ex/images/Button_Y.gif +0 -0
  108. data/doc/ex/images/Button_Z.gif +0 -0
  109. data/doc/ex/images/Cheetah.jpg +0 -0
  110. data/doc/ex/images/Coffee.wmf +0 -0
  111. data/doc/ex/images/Flower_Hat.jpg +0 -0
  112. data/doc/ex/images/Gold_Statue.jpg +0 -0
  113. data/doc/ex/images/Hot_Air_Balloons.jpg +0 -0
  114. data/doc/ex/images/Hot_Air_Balloons_H.jpg +0 -0
  115. data/doc/ex/images/No.wmf +0 -0
  116. data/doc/ex/images/Polynesia.jpg +0 -0
  117. data/doc/ex/images/Red_Rocks.jpg +0 -0
  118. data/doc/ex/images/Shorts.jpg +0 -0
  119. data/doc/ex/images/Snake.wmf +0 -0
  120. data/doc/ex/images/Violin.jpg +0 -0
  121. data/doc/ex/images/graydient230x6.gif +0 -0
  122. data/doc/ex/images/logo400x83.gif +0 -0
  123. data/doc/ex/images/model.miff +0 -0
  124. data/doc/ex/images/notimplemented.gif +0 -0
  125. data/doc/ex/images/smile.miff +0 -0
  126. data/doc/ex/images/spin.gif +0 -0
  127. data/doc/ex/implode.rb +32 -0
  128. data/doc/ex/level.rb +12 -0
  129. data/doc/ex/level_channel.rb +33 -0
  130. data/doc/ex/line.rb +40 -0
  131. data/doc/ex/map.rb +28 -0
  132. data/doc/ex/map_f.rb +15 -0
  133. data/doc/ex/matte_fill_to_border.rb +42 -0
  134. data/doc/ex/matte_floodfill.rb +35 -0
  135. data/doc/ex/matte_replace.rb +42 -0
  136. data/doc/ex/median_filter.rb +28 -0
  137. data/doc/ex/modulate.rb +11 -0
  138. data/doc/ex/mono.rb +23 -0
  139. data/doc/ex/morph.rb +26 -0
  140. data/doc/ex/mosaic.rb +35 -0
  141. data/doc/ex/motion_blur.rb +11 -0
  142. data/doc/ex/negate.rb +11 -0
  143. data/doc/ex/negate_channel.rb +19 -0
  144. data/doc/ex/normalize.rb +11 -0
  145. data/doc/ex/oil_paint.rb +11 -0
  146. data/doc/ex/opacity.rb +38 -0
  147. data/doc/ex/opaque.rb +14 -0
  148. data/doc/ex/ordered_dither.rb +11 -0
  149. data/doc/ex/path.rb +62 -0
  150. data/doc/ex/pattern1.rb +25 -0
  151. data/doc/ex/pattern2.rb +26 -0
  152. data/doc/ex/polygon.rb +24 -0
  153. data/doc/ex/polyline.rb +23 -0
  154. data/doc/ex/posterize.rb +19 -0
  155. data/doc/ex/preview.rb +16 -0
  156. data/doc/ex/qbezierpath.rb +49 -0
  157. data/doc/ex/quantize-m.rb +25 -0
  158. data/doc/ex/radial_blur.rb +19 -0
  159. data/doc/ex/raise.rb +11 -0
  160. data/doc/ex/random_channel_threshold.rb +17 -0
  161. data/doc/ex/random_threshold_channel.rb +18 -0
  162. data/doc/ex/rectangle.rb +33 -0
  163. data/doc/ex/reduce_noise.rb +28 -0
  164. data/doc/ex/roll.rb +9 -0
  165. data/doc/ex/rotate.rb +43 -0
  166. data/doc/ex/rotate_f.rb +14 -0
  167. data/doc/ex/roundrect.rb +32 -0
  168. data/doc/ex/rubyname.rb +31 -0
  169. data/doc/ex/segment.rb +11 -0
  170. data/doc/ex/shade.rb +11 -0
  171. data/doc/ex/shave.rb +15 -0
  172. data/doc/ex/shear.rb +10 -0
  173. data/doc/ex/skewx.rb +50 -0
  174. data/doc/ex/skewy.rb +45 -0
  175. data/doc/ex/smile.rb +124 -0
  176. data/doc/ex/solarize.rb +11 -0
  177. data/doc/ex/splice.rb +16 -0
  178. data/doc/ex/spread.rb +11 -0
  179. data/doc/ex/stegano.rb +50 -0
  180. data/doc/ex/stroke_dasharray.rb +41 -0
  181. data/doc/ex/stroke_linecap.rb +44 -0
  182. data/doc/ex/stroke_linejoin.rb +48 -0
  183. data/doc/ex/stroke_width.rb +47 -0
  184. data/doc/ex/swirl.rb +17 -0
  185. data/doc/ex/text.rb +32 -0
  186. data/doc/ex/text_align.rb +36 -0
  187. data/doc/ex/text_antialias.rb +33 -0
  188. data/doc/ex/text_undercolor.rb +26 -0
  189. data/doc/ex/texture_fill_to_border.rb +34 -0
  190. data/doc/ex/texture_floodfill.rb +31 -0
  191. data/doc/ex/texturefill.rb +25 -0
  192. data/doc/ex/threshold.rb +13 -0
  193. data/doc/ex/to_blob.rb +14 -0
  194. data/doc/ex/translate.rb +37 -0
  195. data/doc/ex/transparent.rb +38 -0
  196. data/doc/ex/trim.rb +25 -0
  197. data/doc/ex/unsharp_mask.rb +28 -0
  198. data/doc/ex/viewex.rb +36 -0
  199. data/doc/ex/wave.rb +9 -0
  200. data/doc/ilist.html +1592 -0
  201. data/doc/image1.html +3009 -0
  202. data/doc/image2.html +2169 -0
  203. data/doc/image3.html +2815 -0
  204. data/doc/imageattrs.html +1319 -0
  205. data/doc/imusage.html +403 -0
  206. data/doc/index.html +418 -0
  207. data/doc/info.html +949 -0
  208. data/doc/magick.html +439 -0
  209. data/doc/scripts/doc.js +9 -0
  210. data/doc/struct.html +1334 -0
  211. data/doc/usage.html +1318 -0
  212. data/examples/describe.rb +44 -0
  213. data/examples/histogram.rb +289 -0
  214. data/examples/image_opacity.rb +29 -0
  215. data/examples/import_export.rb +31 -0
  216. data/examples/pattern_fill.rb +38 -0
  217. data/examples/rotating_text.rb +47 -0
  218. data/examples/thumbnail.rb +65 -0
  219. data/examples/vignette.rb +79 -0
  220. data/ext/RMagick/MANIFEST +239 -0
  221. data/ext/RMagick/extconf.rb.in +21 -0
  222. data/ext/RMagick/rmagick.h +938 -0
  223. data/ext/RMagick/rmagick_config.h.in +170 -0
  224. data/ext/RMagick/rmdraw.c +1308 -0
  225. data/ext/RMagick/rmfill.c +609 -0
  226. data/ext/RMagick/rmilist.c +685 -0
  227. data/ext/RMagick/rmimage.c +7980 -0
  228. data/ext/RMagick/rminfo.c +982 -0
  229. data/ext/RMagick/rmmain.c +1497 -0
  230. data/ext/RMagick/rmutil.c +2685 -0
  231. data/install.rb +1015 -0
  232. data/lib/RMagick.rb +1486 -0
  233. data/metaconfig.in +6 -0
  234. data/post-clean.rb +12 -0
  235. data/post-install.rb +36 -0
  236. data/post-setup.rb +245 -0
  237. data/rmagick.gemspec +22 -0
  238. data/uninstall.rb +71 -0
  239. metadata +286 -0
@@ -0,0 +1,170 @@
1
+ #undef GRAPHICSMAGICK
2
+ /* Introduced in IM 6.0.0, GM 1.1 */
3
+ #undef HAVE_ACQUIREMAGICKMEMORY
4
+ /* Introduced in IM 6.0.0 */
5
+ #undef HAVE_ACQUIRESTRINGINFO
6
+ /* Introduced in IM 5.5.2, GM 1.0 */
7
+ #undef HAVE_ADAPTIVETHRESHOLDIMAGE
8
+ /* Introduced in GM 1.1 */
9
+ #undef HAVE_ADDDEFINITIONS
10
+ /* Introduced in IM 6.0.0, GM 1.1 */
11
+ #undef HAVE_ALLCHANNELS
12
+ /* Introduced in IM 5.5.2, GM 1.0 */
13
+ #undef HAVE_APPENDIMAGETOLIST
14
+ /* Introduced in IM 6.0.0 */
15
+ #undef HAVE_BILEVELIMAGECHANNEL
16
+ /* Introduced in IM 5.5.7, GM 1.1 */
17
+ #undef HAVE_BLACKTHRESHOLDIMAGE
18
+ /* Introduced in IM 6.0.1 */
19
+ #undef HAVE_BLURIMAGECHANNEL
20
+ /* Introduced in IM 6.0.0 */
21
+ #undef HAVE_COLORDODGECOMPOSITEOP
22
+ /* Introduced in IM 6.0.0, GM 1.1 */
23
+ #undef HAVE_COMPAREIMAGECHANNELS
24
+ /* Introduced in IM 6.0.1 */
25
+ #undef HAVE_CONVOLVEIMAGECHANNEL
26
+ /* Introduced in IM 5.5.7, GM 1.1 */
27
+ #undef HAVE_COPYCYANCOMPOSITEOP
28
+ /* Introduced in IM 5.5.1, GM 1.0 */
29
+ #undef HAVE_DISPOSETYPE
30
+ /* Introduced in IM 6.0.0 */
31
+ #undef HAVE_DSTCOMPOSITEOP
32
+ /* Introduced in IM 6.0.1 */
33
+ #undef HAVE_EVALUATEIMAGECHANNEL
34
+ /* Introduced in GM 1.1 */
35
+ #undef HAVE_EXCEPTIONINFO_MODULE
36
+ /* Introduced in IM 5.5.7, GM 1.1 */
37
+ #undef HAVE_EXPORTIMAGEPIXELS
38
+ /* Introduced in GM 1.0, deprecated in GM 1.1.3 */
39
+ /* Introduced in IM 5.5.2, deprecated in IM 6.0.0 */
40
+ #undef HAVE_EXTENDEDSIGNEDINTEGRALTYPE
41
+ #undef HAVE_EXTENDEDUNSIGNEDINTEGRALTYPE
42
+ /* Introduced in IM 5.5.5 */
43
+ #undef HAVE_FUZZYCOLORCOMPARE
44
+ /* Introduced in IM 6.0.0, GM 1.1 */
45
+ #undef HAVE_GAMMAIMAGECHANNEL
46
+ /* Introduced in IM 6.0.1 */
47
+ #undef HAVE_GAUSSIANBLURIMAGECHANNEL
48
+ /* Introduced in GM 1.1 */
49
+ #undef HAVE_GETCOLORHISTOGRAM
50
+ /* Introduced in IM 6.0.1 */
51
+ #undef HAVE_GETCOLORINFOLIST
52
+ /* API changed in IM 6.1.3 */
53
+ #undef HAVE_OLD_GETCOLORINFOLIST
54
+ /* Introduced in GM 1.1 */
55
+ #undef HAVE_GETCOLORINFOARRAY
56
+ /* Introduced in IM 6.0.0, GM 1.1 */
57
+ #undef HAVE_GETIMAGECHANNELDEPTH
58
+ /* Introduced in IM 6.0.0, GM 1.1 */
59
+ #undef HAVE_GETIMAGECHANNELEXTREMA
60
+ /* Introduced in IM 6.0.0, GM 1.1 */
61
+ #undef HAVE_GETIMAGECHANNELMEAN
62
+ /* Introduced in IM 6.0.0, GM 1.1 */
63
+ #undef HAVE_GETIMAGEHISTOGRAM
64
+ /* Introduced in IM 6.0.0, GM 1.1 */
65
+ #undef HAVE_GETIMAGEPROFILE
66
+ /* Introduced in IM 6.0.0 */
67
+ #undef HAVE_GETIMAGEQUANTUMDEPTH
68
+ /* Introduced in IM 6.0.0, signature changed in 6.0.5 */
69
+ #undef HAVE_OLD_GETIMAGEQUANTUMDEPTH
70
+ /* Introduced in GM 1.1 */
71
+ #undef HAVE_GETIMAGESTATISTICS
72
+ /* Introduced in IM 5.5.2, GM 1.0 */
73
+ #undef HAVE_GETLOCALEEXCEPTIONMESSAGE
74
+ /* Introduced in IM 5.5.1, GM 1.0 */
75
+ #undef HAVE_GETMAGICKGEOMETRY
76
+ /* Introduced in GM 1.1 */
77
+ #undef HAVE_GETMAGICKINFOARRAY
78
+ /* Introduced in IM 6.0.1 */
79
+ #undef HAVE_GETMAGICKINFOLIST
80
+ /* Introduced in IM 6.1.5 */
81
+ #undef HAVE_GETMULTILINETYPEMETRICS
82
+ /* API changed in IM 6.1.3 */
83
+ #undef HAVE_OLD_GETMAGICKINFOLIST
84
+ #undef HAVE_GETNEXTIMAGEINLIST
85
+ /* Introduced in IM 6.0.0 */
86
+ #undef HAVE_GETNEXTIMAGEPROFILE
87
+ /* Introduced in IM 6.0.1 */
88
+ #undef HAVE_GETTYPEINFOLIST
89
+ /* API changed in IM 6.1.3 */
90
+ #undef HAVE_OLD_GETTYPEINFOLIST
91
+ /* Introduced in GM 1.0 */
92
+ #undef HAVE_GRAYSCALEPSEUDOCLASSIMAGE
93
+ /* Introduced in IM 6.0.0 */
94
+ #undef HAVE_HSBCOLORSPACE
95
+ /* Introduced in IM 5.5.7, GM 1.0 */
96
+ #undef HAVE_HSLCOLORSPACE
97
+ /* Introduced in IM 5.5.7, GM 1.0 */
98
+ #undef HAVE_HWBCOLORSPACE
99
+ /* Introduced in IM 6.0.0, GM 1.1 */
100
+ #undef HAVE_INDEXCHANNEL
101
+ /* Introduced in IM 5.5.6 */
102
+ #undef HAVE_IMAGE_EXTRACT_INFO
103
+ /* Introduced in IM 5.5.6 */
104
+ #undef HAVE_IMAGEINFO_NUMBER_SCENES
105
+ /* Introduced in IM 5.5.7, GM 1.1 */
106
+ #undef HAVE_IMPORTIMAGEPIXELS
107
+ #undef HAVE_INTTYPES_H
108
+ /* Introduced in IM 5.5.3, GM 1.0 */
109
+ #undef HAVE_LEVELIMAGECHANNEL
110
+ /* Introduced in IM 6.0.2 */
111
+ #undef HAVE_MAGICKBOOLEANTYPE
112
+ /* Introduced in IM 5.5.3, GM 1.0 */
113
+ #undef HAVE_MAGICK_INT64_T
114
+ #undef HAVE_MAGICK_UINT64_T
115
+ /* Introduced in IM 6.0.0 */
116
+ #undef HAVE_MAGICKOFFSETTYPE
117
+ /* Introduced in IM 6.0.0, GM 1.1 */
118
+ #undef HAVE_MAGICKSIZETYPE
119
+ #undef HAVE_MEMORY_H
120
+ /* Introduced in IM 6.0.0, GM 1.1 */
121
+ #undef HAVE_NEGATEIMAGECHANNEL
122
+ /* Introduced in IM 5.5.1, GM 1.0 */
123
+ #undef HAVE_NOCOMPLIANCE
124
+ /* Introduced in IM 6.1.0 */
125
+ #undef HAVE_NORMALIZEIMAGECHANNEL
126
+ /* Introduced in IM 5.5.4 */
127
+ #undef HAVE_PARSESIZEGEOMETRY
128
+ /* Introduced in IM 6.0.0 */
129
+ #undef HAVE_POSTERIZEIMAGE
130
+ /* Introduced in IM 5.5.1, GM 1.0 */
131
+ #undef HAVE_PREVIEWIMAGE
132
+ #undef HAVE_QUANTUMOPERATORREGIONIMAGE
133
+ #undef HAVE_RADIALBLURIMAGE
134
+ #undef HAVE_RANDOMCHANNELTHRESHOLDIMAGE
135
+ #undef HAVE_RANDOMTHRESHOLDIMAGECHANNEL
136
+ #undef HAVE_REMOVEFIRSTIMAGEFROMLIST
137
+ #undef HAVE_REPLACECOMPOSITEOP
138
+ #undef HAVE_SEPARATEIMAGECHANNEL
139
+ #undef HAVE_SETIMAGECOLORSPACE
140
+ /* Introduced in IM 6.0.0, GM 1.1 */
141
+ #undef HAVE_SETIMAGECHANNELDEPTH
142
+ #undef HAVE_SETIMAGEOPTION
143
+ #undef HAVE_SETLOGFORMAT
144
+ /* Introduced in IM 6.0.1 */
145
+ #undef HAVE_SHARPENIMAGECHANNEL
146
+ #undef HAVE_SNPRINTF
147
+ #undef HAVE_SPLICEIMAGE
148
+ #undef HAVE_STDINT_H
149
+ #undef HAVE_STDLIB_H
150
+ #undef HAVE_STRING_H
151
+ #undef HAVE_STRINGS_H
152
+ #undef HAVE_STRIPIMAGE
153
+ #undef HAVE_SYS_STAT_H
154
+ #undef HAVE_SYS_TYPES_H
155
+ #undef HAVE_THRESHOLDIMAGECHANNEL
156
+ #undef HAVE_THUMBNAILIMAGE
157
+ #undef HAVE_TINTIMAGE
158
+ #undef HAVE_UNISTD_H
159
+ /* Introduced in IM 6.1.0 */
160
+ #undef HAVE_UNSHARPMASKIMAGECHANNEL
161
+ #undef HAVE_WHITETHRESHOLDIMAGE
162
+ #undef HAVE_XIMPORTIMAGE
163
+ #undef MAGICKNAME
164
+ #undef PACKAGE_BUGREPORT
165
+ #undef PACKAGE_NAME
166
+ #undef PACKAGE_STRING
167
+ #undef PACKAGE_TARNAME
168
+ #undef PACKAGE_VERSION
169
+ #undef RUBY_VERSION_STRING
170
+
@@ -0,0 +1,1308 @@
1
+ /* $Id: rmdraw.c,v 1.21 2004/12/17 22:42:51 rmagick Exp $ */
2
+ /*============================================================================\
3
+ | Copyright (C) 2004 by Timothy P. Hunter
4
+ | Name: rmdraw.c
5
+ | Author: Tim Hunter
6
+ | Purpose: Contains Draw class methods.
7
+ | Contains Montage class methods.
8
+ \============================================================================*/
9
+
10
+ #include "rmagick.h"
11
+ #include "float.h"
12
+
13
+ static void mark_Draw(void *);
14
+ static void destroy_Draw(void *);
15
+ static void destroy_Montage(void *);
16
+
17
+ typedef MagickBooleanType (get_type_metrics_func_t)(Image *, const DrawInfo *, TypeMetric *);
18
+ static VALUE get_type_metrics(int, VALUE *, VALUE, get_type_metrics_func_t *);
19
+
20
+
21
+ /*
22
+ Method: Draw#affine=
23
+ Purpose: set the affine matrix from an Magick::AffineMatrix
24
+ */
25
+ VALUE
26
+ Draw_affine_eq(VALUE self, VALUE matrix)
27
+ {
28
+ Draw *draw;
29
+
30
+ rm_check_frozen(self);
31
+ Data_Get_Struct(self, Draw, draw);
32
+ AffineMatrix_to_AffineMatrix(&draw->info->affine, matrix);
33
+ return self;
34
+ }
35
+
36
+ /*
37
+ Method: Draw#align=
38
+ Purpose: set the text alignment
39
+ */
40
+ VALUE
41
+ Draw_align_eq(VALUE self, VALUE align)
42
+ {
43
+ Draw *draw;
44
+
45
+ rm_check_frozen(self);
46
+ Data_Get_Struct(self, Draw, draw);
47
+ VALUE_TO_ENUM(align, draw->info->align, AlignType);
48
+ return self;
49
+ }
50
+
51
+ /*
52
+ Method: Draw#decorate=
53
+ Purpose: decorate attribute writer
54
+ */
55
+ VALUE
56
+ Draw_decorate_eq(VALUE self, VALUE decorate)
57
+ {
58
+ Draw *draw;
59
+
60
+ rm_check_frozen(self);
61
+ Data_Get_Struct(self, Draw, draw);
62
+ VALUE_TO_ENUM(decorate, draw->info->decorate, DecorationType);
63
+ return self;
64
+ }
65
+
66
+ /*
67
+ Method: Draw#density=
68
+ Purpose: density attribute writer
69
+ */
70
+ VALUE
71
+ Draw_density_eq(VALUE self, VALUE density)
72
+ {
73
+ Draw *draw;
74
+
75
+ rm_check_frozen(self);
76
+ Data_Get_Struct(self, Draw, draw);
77
+ magick_clone_string(&draw->info->density, STRING_PTR(density));
78
+
79
+ return self;
80
+ }
81
+
82
+ /*
83
+ Method: Draw#encoding=
84
+ Purpose: encoding attribute writer
85
+ */
86
+ VALUE
87
+ Draw_encoding_eq(VALUE self, VALUE encoding)
88
+ {
89
+ Draw *draw;
90
+
91
+ rm_check_frozen(self);
92
+ Data_Get_Struct(self, Draw, draw);
93
+ magick_clone_string(&draw->info->encoding, STRING_PTR(encoding));
94
+
95
+ return self;
96
+ }
97
+
98
+ /*
99
+ Method: Draw#fill=
100
+ Purpose: fill attribute writer
101
+ */
102
+ VALUE
103
+ Draw_fill_eq(VALUE self, VALUE fill)
104
+ {
105
+ Draw *draw;
106
+
107
+ rm_check_frozen(self);
108
+ Data_Get_Struct(self, Draw, draw);
109
+ Color_to_PixelPacket(&draw->info->fill, fill);
110
+ return self;
111
+ }
112
+
113
+ /*
114
+ Method: Draw#font=
115
+ Purpose: font attribute writer
116
+ */
117
+ VALUE
118
+ Draw_font_eq(VALUE self, VALUE font)
119
+ {
120
+ Draw *draw;
121
+
122
+ rm_check_frozen(self);
123
+ Data_Get_Struct(self, Draw, draw);
124
+ magick_clone_string(&draw->info->font, STRING_PTR(font));
125
+
126
+ return self;
127
+ }
128
+
129
+ /*
130
+ Method: Draw#font_family=
131
+ Purpose: font_family attribute writer
132
+ */
133
+ VALUE
134
+ Draw_font_family_eq(VALUE self, VALUE family)
135
+ {
136
+ Draw *draw;
137
+
138
+ rm_check_frozen(self);
139
+ Data_Get_Struct(self, Draw, draw);
140
+ magick_clone_string(&draw->info->family, STRING_PTR(family));
141
+
142
+ return self;
143
+ }
144
+
145
+ /*
146
+ Method: Draw#font_stretch=
147
+ Purpose: font_stretch attribute writer
148
+ */
149
+ VALUE
150
+ Draw_font_stretch_eq(VALUE self, VALUE stretch)
151
+ {
152
+ Draw *draw;
153
+
154
+ rm_check_frozen(self);
155
+ Data_Get_Struct(self, Draw, draw);
156
+ VALUE_TO_ENUM(stretch, draw->info->stretch, StretchType);
157
+ return self;
158
+ }
159
+
160
+ /*
161
+ Method: Draw#font_style=
162
+ Purpose: font_style attribute writer
163
+ */
164
+ VALUE
165
+ Draw_font_style_eq(VALUE self, VALUE style)
166
+ {
167
+ Draw *draw;
168
+
169
+ rm_check_frozen(self);
170
+ Data_Get_Struct(self, Draw, draw);
171
+ VALUE_TO_ENUM(style, draw->info->style, StyleType);
172
+ return self;
173
+ }
174
+
175
+ /*
176
+ Method: Draw#font_weight=
177
+ Purpose: font_weight attribute writer
178
+ Notes: The font weight can be one of the font weight constants
179
+ or a number between 100 and 900
180
+ */
181
+
182
+
183
+ VALUE
184
+ Draw_font_weight_eq(VALUE self, VALUE weight)
185
+ {
186
+ Draw *draw;
187
+ WeightType w;
188
+
189
+ rm_check_frozen(self);
190
+ Data_Get_Struct(self, Draw, draw);
191
+
192
+ if (FIXNUM_P(weight))
193
+ {
194
+ w = (WeightType) FIX2INT(weight);
195
+ if (w < 100 || w > 900)
196
+ {
197
+ rb_raise(rb_eArgError, "invalid font weight (%d given)", w);
198
+ }
199
+ draw->info->weight = w;
200
+ }
201
+ else
202
+ {
203
+ VALUE_TO_ENUM(weight, w, WeightType);
204
+ switch (w)
205
+ {
206
+ case AnyWeight:
207
+ draw->info->weight = 0;
208
+ break;
209
+ case NormalWeight:
210
+ draw->info->weight = 400;
211
+ break;
212
+ case BoldWeight:
213
+ draw->info->weight = 700;
214
+ break;
215
+ case BolderWeight:
216
+ if (draw->info->weight <= 800)
217
+ draw->info->weight += 100;
218
+ break;
219
+ case LighterWeight:
220
+ if (draw->info->weight >= 100)
221
+ draw->info->weight -= 100;
222
+ break;
223
+ default:
224
+ rb_raise(rb_eArgError, "unknown font weight");
225
+ break;
226
+ }
227
+ }
228
+
229
+ return self;
230
+ }
231
+
232
+ /*
233
+ Method: Draw#gravity=
234
+ Purpose: gravity attribute writer
235
+ Notes: From Magick++'s Image.h header file:
236
+ Gravity affects text placement in bounding area according to rules:
237
+ NorthWestGravity text bottom-left corner placed at top-left
238
+ NorthGravity text bottom-center placed at top-center
239
+ NorthEastGravity text bottom-right corner placed at top-right
240
+ WestGravity text left-center placed at left-center
241
+ CenterGravity text center placed at center
242
+ EastGravity text right-center placed at right-center
243
+ SouthWestGravity text top-left placed at bottom-left
244
+ SouthGravity text top-center placed at bottom-center
245
+ SouthEastGravity text top-right placed at bottom-right
246
+ */
247
+ VALUE
248
+ Draw_gravity_eq(VALUE self, VALUE grav)
249
+ {
250
+ Draw *draw;
251
+
252
+ rm_check_frozen(self);
253
+ Data_Get_Struct(self, Draw, draw);
254
+ VALUE_TO_ENUM(grav, draw->info->gravity, GravityType);
255
+
256
+ return self;
257
+ }
258
+
259
+ /*
260
+ Method: Draw#pointsize=
261
+ Purpose: pointsize attribute writer
262
+ */
263
+ VALUE
264
+ Draw_pointsize_eq(VALUE self, VALUE pointsize)
265
+ {
266
+ Draw *draw;
267
+
268
+ rm_check_frozen(self);
269
+ Data_Get_Struct(self, Draw, draw);
270
+ draw->info->pointsize = NUM2DBL(pointsize);
271
+ return self;
272
+ }
273
+
274
+ /*
275
+ Method: Magick::Draw#rotation=degrees
276
+ Purpose: set rotation attribute value
277
+ Notes: Taken from Magick++'s Magick::Image::annotate method
278
+ Copyright Bob Friesenhahn, 1999, 2000, 2001, 2002
279
+ */
280
+ VALUE
281
+ Draw_rotation_eq(VALUE self, VALUE deg)
282
+ {
283
+ Draw *draw;
284
+ double degrees;
285
+ AffineMatrix affine, current;
286
+
287
+ rm_check_frozen(self);
288
+ Data_Get_Struct(self, Draw, draw);
289
+
290
+ degrees = NUM2DBL(deg);
291
+ if (fabs(degrees) > DBL_EPSILON)
292
+ {
293
+ affine.sx=1.0;
294
+ affine.rx=0.0;
295
+ affine.ry=0.0;
296
+ affine.sy=1.0;
297
+ affine.tx=0.0;
298
+ affine.ty=0.0;
299
+
300
+ current = draw->info->affine;
301
+ affine.sx=cos(DegreesToRadians(fmod(degrees,360.0)));
302
+ affine.rx=sin(DegreesToRadians(fmod(degrees,360.0)));
303
+ affine.ry=(-sin(DegreesToRadians(fmod(degrees,360.0))));
304
+ affine.sy=cos(DegreesToRadians(fmod(degrees,360.0)));
305
+
306
+ draw->info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
307
+ draw->info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
308
+ draw->info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
309
+ draw->info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
310
+ draw->info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
311
+ }
312
+
313
+ return self;
314
+ }
315
+
316
+ /*
317
+ Method: Draw#stroke=
318
+ Purpose: stroke attribute writer
319
+ */
320
+ VALUE
321
+ Draw_stroke_eq(VALUE self, VALUE stroke)
322
+ {
323
+ Draw *draw;
324
+
325
+ rm_check_frozen(self);
326
+ Data_Get_Struct(self, Draw, draw);
327
+ Color_to_PixelPacket(&draw->info->stroke, stroke);
328
+ return self;
329
+ }
330
+
331
+ /*
332
+ Method: Draw#stroke_width=
333
+ Purpose: stroke_width attribute writer
334
+ */
335
+ VALUE
336
+ Draw_stroke_width_eq(VALUE self, VALUE stroke_width)
337
+ {
338
+ Draw *draw;
339
+
340
+ rm_check_frozen(self);
341
+ Data_Get_Struct(self, Draw, draw);
342
+ draw->info->stroke_width = NUM2DBL(stroke_width);
343
+ return self;
344
+ }
345
+
346
+ /*
347
+ Method: Draw#text_antialias=
348
+ Purpose: text_antialias attribute writer
349
+ */
350
+ VALUE
351
+ Draw_text_antialias_eq(VALUE self, VALUE text_antialias)
352
+ {
353
+ Draw *draw;
354
+
355
+ rm_check_frozen(self);
356
+ Data_Get_Struct(self, Draw, draw);
357
+ draw->info->text_antialias = RTEST(text_antialias);
358
+ return self;
359
+ }
360
+
361
+ /*
362
+ Method: Draw#undercolor=
363
+ Purpose: undercolor attribute writer
364
+ */
365
+ VALUE
366
+ Draw_undercolor_eq(VALUE self, VALUE undercolor)
367
+ {
368
+ Draw *draw;
369
+
370
+ rm_check_frozen(self);
371
+ Data_Get_Struct(self, Draw, draw);
372
+ Color_to_PixelPacket(&draw->info->undercolor, undercolor);
373
+ return self;
374
+ }
375
+
376
+ /*
377
+ Method: Draw#annotate(img, w, h, x, y, text) <{optional parms}>
378
+ Purpose: annotates an image with text
379
+ Returns: self
380
+ Notes: Additional Draw attribute methods may be called in the
381
+ optional block, which is executed in the context of an
382
+ Draw object.
383
+ */
384
+ VALUE Draw_annotate(
385
+ VALUE self,
386
+ VALUE image_arg,
387
+ VALUE width_arg,
388
+ VALUE height_arg,
389
+ VALUE x_arg,
390
+ VALUE y_arg,
391
+ VALUE text)
392
+ {
393
+ Draw *draw;
394
+ Image *image;
395
+ unsigned long width, height;
396
+ long x, y;
397
+ AffineMatrix keep;
398
+ char geometry_str[50];
399
+
400
+ // Save the affine matrix in case it is modified by
401
+ // Draw#rotation=
402
+ Data_Get_Struct(self, Draw, draw);
403
+ keep = draw->info->affine;
404
+
405
+ // If we have an optional parm block, run it in self's context,
406
+ // allowing the app a chance to modify the object's attributes
407
+ if (rb_block_given_p())
408
+ {
409
+ (void)rb_obj_instance_eval(0, NULL, self);
410
+ }
411
+
412
+ rm_check_frozen(ImageList_cur_image(image_arg));
413
+ Data_Get_Struct(ImageList_cur_image(image_arg), Image, image);
414
+
415
+ // Copy text to Draw structure
416
+ magick_clone_string(&draw->info->text, STRING_PTR(text));
417
+
418
+ // Create geometry string, copy to Draw structure, overriding
419
+ // any previously existing value.
420
+ width = NUM2ULONG(width_arg);
421
+ height = NUM2ULONG(height_arg);
422
+ x = NUM2LONG(x_arg);
423
+ y = NUM2LONG(y_arg);
424
+
425
+ // If either the width or height is 0, both must be 0.
426
+ if (width == 0 || height == 0)
427
+ {
428
+ if (width != 0 || height != 0)
429
+ {
430
+ rb_raise(rb_eArgError, "invalid geometry %lux%lu%+ld%+ld", width, height, x, y);
431
+ }
432
+ sprintf(geometry_str, "%+ld%+ld", x, y);
433
+ }
434
+
435
+ // WxH is non-zero
436
+ else
437
+ {
438
+ sprintf(geometry_str, "%lux%lu%+ld%+ld", width, height, x, y);
439
+ }
440
+
441
+ magick_clone_string(&draw->info->geometry, geometry_str);
442
+
443
+ (void) AnnotateImage(image, draw->info);
444
+
445
+ draw->info->affine = keep;
446
+
447
+ HANDLE_ERROR_IMG(image)
448
+
449
+ return self;
450
+ }
451
+
452
+
453
+ /*
454
+ Method: Draw#clone
455
+ Notes: see dup, init_copy
456
+ */
457
+ VALUE
458
+ Draw_clone(VALUE self)
459
+ {
460
+ volatile VALUE clone;
461
+
462
+ clone = Draw_dup(self);
463
+ if (OBJ_FROZEN(self))
464
+ {
465
+ (void)rb_obj_freeze(clone);
466
+ }
467
+
468
+ return clone;
469
+ }
470
+
471
+
472
+ /*
473
+ Method: Draw#composite(x,y,width,height,img,operator=OverCompositeOp)
474
+ Purpose: Implement the "image" drawing primitive
475
+ Notes: The "img" argument can be either an ImageList object
476
+ or an Image argument.
477
+ */
478
+ VALUE
479
+ Draw_composite(int argc, VALUE *argv, VALUE self)
480
+ {
481
+ Draw *draw;
482
+ const char *op = "Over";
483
+ double x, y, width, height;
484
+ CompositeOperator cop = OverCompositeOp;
485
+ volatile VALUE image;
486
+ Image *comp_img;
487
+ struct TmpFile_Name *tmpfile;
488
+ char name[MaxTextExtent];
489
+ // Buffer for "image" primitive
490
+ char primitive[MaxTextExtent];
491
+
492
+ if (argc < 5 || argc > 6)
493
+ {
494
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 5 or 6)", argc);
495
+ }
496
+
497
+ x = NUM2DBL(argv[0]);
498
+ y = NUM2DBL(argv[1]);
499
+ width = NUM2DBL(argv[2]);
500
+ height = NUM2DBL(argv[3]);
501
+
502
+ // The default composition operator is "Over".
503
+ if (argc == 6)
504
+ {
505
+ VALUE_TO_ENUM(argv[5], cop, CompositeOperator);
506
+
507
+ switch(cop)
508
+ {
509
+ case AddCompositeOp:
510
+ op = "Add";
511
+ break;
512
+ case AtopCompositeOp:
513
+ op = "Atop";
514
+ break;
515
+ case BumpmapCompositeOp:
516
+ op = "Bumpmap";
517
+ break;
518
+ case ClearCompositeOp:
519
+ op = "Clear";
520
+ break;
521
+ case CopyBlueCompositeOp:
522
+ op = "CopyBlue";
523
+ break;
524
+ case CopyGreenCompositeOp:
525
+ op = "CopyGreen";
526
+ break;
527
+ case CopyOpacityCompositeOp:
528
+ op = "CopyOpacity";
529
+ break;
530
+ case CopyRedCompositeOp:
531
+ op = "CopyRed";
532
+ break;
533
+ case CopyCompositeOp:
534
+ op = "Copy";
535
+ break;
536
+ case DifferenceCompositeOp:
537
+ op = "Difference";
538
+ break;
539
+ case InCompositeOp:
540
+ op = "In";
541
+ break;
542
+ case MinusCompositeOp:
543
+ op = "Minus";
544
+ break;
545
+ case MultiplyCompositeOp:
546
+ op = "Multiply";
547
+ break;
548
+ case OutCompositeOp:
549
+ op = "Out";
550
+ break;
551
+ case OverCompositeOp:
552
+ op = "Over";
553
+ break;
554
+ case PlusCompositeOp:
555
+ op = "Plus";
556
+ break;
557
+ case SubtractCompositeOp:
558
+ op = "Subtract";
559
+ break;
560
+ case XorCompositeOp:
561
+ op = "Xor";
562
+ break;
563
+ default:
564
+ rb_raise(rb_eArgError, "unknown composite operator (%d)", cop);
565
+ break;
566
+ }
567
+ }
568
+
569
+ Data_Get_Struct(self, Draw, draw);
570
+
571
+ // Retrieve the image to composite
572
+ image = ImageList_cur_image(argv[4]);
573
+
574
+ // Create a temp copy of the composite image
575
+ Data_Get_Struct(image, Image, comp_img);
576
+ rm_write_temp_image(comp_img, name);
577
+
578
+ // Add the temp filename to the filename array.
579
+ // Use Magick storage since we need to keep the list around
580
+ // until destroy_Draw is called.
581
+ tmpfile = magick_malloc(sizeof(struct TmpFile_Name)+strlen(name));
582
+ strcpy(tmpfile->name, name);
583
+ tmpfile->next = draw->tmpfile_ary;
584
+ draw->tmpfile_ary = tmpfile;
585
+
586
+ // Form the drawing primitive
587
+ (void) sprintf(primitive, "image %s %g,%g,%g,%g '%s'", op, x, y, width, height, name);
588
+
589
+
590
+ // Send "primitive" to self.
591
+ (void) rb_funcall(self, rb_intern("primitive"), 1, rb_str_new2(primitive));
592
+
593
+ return self;
594
+ }
595
+
596
+ /*
597
+ Method: Draw#draw(i)
598
+ Purpose: Execute the stored drawing primitives on the current image
599
+ image
600
+ */
601
+ VALUE
602
+ Draw_draw(VALUE self, VALUE image_arg)
603
+ {
604
+ Draw *draw;
605
+ Image *image;
606
+
607
+ Data_Get_Struct(self, Draw, draw);
608
+ if (draw->primitives == 0)
609
+ {
610
+ rb_raise(rb_eArgError, "nothing to draw");
611
+ }
612
+
613
+ rm_check_frozen(ImageList_cur_image(image_arg));
614
+ Data_Get_Struct(ImageList_cur_image(image_arg), Image, image);
615
+
616
+ // Point the DrawInfo structure at the current set of primitives.
617
+ magick_clone_string(&(draw->info->primitive), STRING_PTR(draw->primitives));
618
+
619
+ (void) DrawImage(image, draw->info);
620
+ HANDLE_ERROR_IMG(image)
621
+
622
+ magick_free(draw->info->primitive);
623
+ draw->info->primitive = NULL;
624
+
625
+ return self;
626
+ }
627
+
628
+
629
+ /*
630
+ Methods: Draw#dup
631
+ Purpose: Copy a Draw object
632
+ Notes: Constructs a new Draw object, then calls initialize_copy
633
+ */
634
+ VALUE
635
+ Draw_dup(VALUE self)
636
+ {
637
+ Draw *draw;
638
+ volatile VALUE dup;
639
+
640
+ draw = ALLOC(Draw);
641
+ memset(draw, 0, sizeof(Draw));
642
+ dup = Data_Wrap_Struct(CLASS_OF(self), mark_Draw, destroy_Draw, draw);
643
+ if (rb_obj_tainted(self))
644
+ {
645
+ (void)rb_obj_taint(dup);
646
+ }
647
+ return rb_funcall(dup, ID_initialize_copy, 1, self);
648
+ }
649
+
650
+
651
+ /*
652
+ Method: Draw#get_type_metrics([image, ]text)
653
+ Draw#get_multiline_type_metrics([image, ]text)
654
+ Purpose: returns measurements for a given font and text string
655
+ Notes: If the image argument has been omitted, use a dummy
656
+ image, but make sure the text has none of the special
657
+ characters that refer to image attributes.
658
+ */
659
+ VALUE
660
+ Draw_get_type_metrics(
661
+ int argc,
662
+ VALUE *argv,
663
+ VALUE self)
664
+ {
665
+ return get_type_metrics(argc, argv, self, GetTypeMetrics);
666
+ }
667
+
668
+
669
+ VALUE
670
+ Draw_get_multiline_type_metrics(
671
+ int argc,
672
+ VALUE *argv,
673
+ VALUE self)
674
+ {
675
+ #if defined(HAVE_GETMULTILINETYPEMETRICS)
676
+ return get_type_metrics(argc, argv, self, GetMultilineTypeMetrics);
677
+ #else
678
+ rm_not_implemented();
679
+ return (VALUE)0;
680
+ #endif
681
+ }
682
+
683
+ /*
684
+ Method: Draw#initialize_copy
685
+ Purpose: initialize clone, dup methods
686
+ */
687
+ VALUE Draw_init_copy(VALUE self, VALUE orig)
688
+ {
689
+ Draw *copy, *original;
690
+
691
+ Data_Get_Struct(orig, Draw, original);
692
+ Data_Get_Struct(self, Draw, copy);
693
+
694
+ copy->info = CloneDrawInfo(NULL, original->info);
695
+ if (!copy->info)
696
+ {
697
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
698
+ }
699
+
700
+ if (original->primitives)
701
+ {
702
+ copy->primitives = rb_str_dup(original->primitives);
703
+ }
704
+
705
+ return self;
706
+ }
707
+
708
+ /*
709
+ Method: Draw#initialize <{ info initializers }>
710
+ Purpose: Initialize Draw object
711
+ Notes: Here are the DrawInfo fields that are copied from Info.
712
+ These are the only Info fields that can be usefully
713
+ set in the initializer block.
714
+
715
+ DrawInfo Info
716
+ -------- ---------
717
+ stroke_antialias antialias
718
+ font font
719
+ density density
720
+ text_antialias antialias
721
+ pointsize pointsize
722
+ border_color border_color
723
+ server_name server_name
724
+ debug debug
725
+ */
726
+ VALUE
727
+ Draw_initialize(VALUE self)
728
+ {
729
+ Draw *draw;
730
+ Info *info;
731
+ volatile VALUE info_obj;
732
+
733
+ Data_Get_Struct(self, Draw, draw);
734
+
735
+ // Create a new Info object, running the info parms block in the process
736
+ info_obj = rm_info_new();
737
+
738
+ // Use the Info structure to create the DrawInfo structure
739
+ Data_Get_Struct(info_obj, Info, info);
740
+ draw->info = CloneDrawInfo(info, NULL);
741
+
742
+ draw->primitives = (VALUE)0;
743
+ draw->tmpfile_ary = NULL;
744
+
745
+ return self;
746
+ }
747
+
748
+ /*
749
+ Method: inspect
750
+ Purpose: display the primitives
751
+ */
752
+ VALUE
753
+ Draw_inspect(VALUE self)
754
+ {
755
+ Draw *draw;
756
+
757
+ Data_Get_Struct(self, Draw, draw);
758
+ return draw->primitives ? draw->primitives : rb_str_new2("(no primitives defined)");
759
+ }
760
+
761
+ /*
762
+ Method: Draw.new/Draw.allocate
763
+ Purpose: Create a new Draw object
764
+ Raises: ImageMagickError if no memory
765
+ */
766
+ VALUE
767
+ #if defined(HAVE_RB_DEFINE_ALLOC_FUNC)
768
+ Draw_alloc(VALUE class)
769
+ #else
770
+ Draw_new(VALUE class)
771
+ #endif
772
+ {
773
+ Draw *draw;
774
+ volatile VALUE draw_obj;
775
+
776
+ draw = ALLOC(Draw);
777
+ memset(draw, 0, sizeof(Draw));
778
+ draw_obj = Data_Wrap_Struct(class, mark_Draw, destroy_Draw, draw);
779
+
780
+ #if !defined(HAVE_RB_DEFINE_ALLOC_FUNC)
781
+ rb_obj_call_init(draw_obj, 0, NULL);
782
+ #endif
783
+
784
+ return draw_obj;
785
+ }
786
+
787
+ /*
788
+ Method: Draw#primitive
789
+ Purpose: Add a drawing primitive to the list of primitives in the
790
+ Draw object
791
+ */
792
+ VALUE
793
+ Draw_primitive(VALUE self, VALUE primitive)
794
+ {
795
+ Draw *draw;
796
+
797
+ rm_check_frozen(self);
798
+ Data_Get_Struct(self, Draw, draw);
799
+
800
+ if (draw->primitives == (VALUE)0)
801
+ {
802
+ draw->primitives = primitive;
803
+ }
804
+ else
805
+ {
806
+ draw->primitives = rb_str_concat(draw->primitives, rb_str_new2("\n"));
807
+ draw->primitives = rb_str_concat(draw->primitives, primitive);
808
+ }
809
+
810
+ return self;
811
+ }
812
+
813
+ /*
814
+ Static: mark_Draw
815
+ Purpose: mark referenced objects
816
+ */
817
+ static void
818
+ mark_Draw(void *drawptr)
819
+ {
820
+ Draw *draw = (Draw *)drawptr;
821
+
822
+ if (draw->primitives != (VALUE)0)
823
+ {
824
+ rb_gc_mark(draw->primitives);
825
+ }
826
+ }
827
+
828
+ /*
829
+ Static: destroy_Draw
830
+ Purpose: free the memory associated with an Draw object
831
+ */
832
+ static void
833
+ destroy_Draw(void *drawptr)
834
+ {
835
+ Draw *draw = (Draw *)drawptr;
836
+ struct TmpFile_Name *tmpfile;
837
+
838
+ DestroyDrawInfo(draw->info);
839
+
840
+ // Erase any temporary image files.
841
+ while (draw->tmpfile_ary)
842
+ {
843
+ tmpfile = draw->tmpfile_ary;
844
+ draw->tmpfile_ary = draw->tmpfile_ary->next;
845
+ rm_delete_temp_image(tmpfile->name);
846
+ magick_free(tmpfile);
847
+ }
848
+
849
+ xfree(drawptr);
850
+ }
851
+
852
+ /*
853
+ Method: Magick::Montage#background_color(color-name)
854
+ Purpose: set background_color value
855
+ */
856
+ VALUE
857
+ Montage_background_color_eq(VALUE self, VALUE color)
858
+ {
859
+ Montage *montage;
860
+
861
+ Data_Get_Struct(self, Montage, montage);
862
+ Color_to_PixelPacket(&montage->info->background_color, color);
863
+ return self;
864
+ }
865
+
866
+ /*
867
+ Method: Magick::Montage#border_color(color-name)
868
+ Purpose: set border_color value
869
+ */
870
+ VALUE
871
+ Montage_border_color_eq(VALUE self, VALUE color)
872
+ {
873
+ Montage *montage;
874
+
875
+ Data_Get_Struct(self, Montage, montage);
876
+ Color_to_PixelPacket(&montage->info->border_color, color);
877
+ return self;
878
+ }
879
+
880
+ /*
881
+ Method: Magick::Montage#border_width(width)
882
+ Purpose: set border_width value
883
+ */
884
+ VALUE
885
+ Montage_border_width_eq(VALUE self, VALUE width)
886
+ {
887
+ Montage *montage;
888
+
889
+ Data_Get_Struct(self, Montage, montage);
890
+ montage->info->border_width = NUM2ULONG(width);
891
+ return self;
892
+ }
893
+
894
+ /*
895
+ Method: Magick::Montage#compose(width)
896
+ Purpose: set a composition operator
897
+ */
898
+ VALUE
899
+ Montage_compose_eq(VALUE self, VALUE compose)
900
+ {
901
+ Montage *montage;
902
+
903
+ Data_Get_Struct(self, Montage, montage);
904
+ VALUE_TO_ENUM(compose, montage->compose, CompositeOperator);
905
+ return self;
906
+ }
907
+
908
+ /*
909
+ Method: Magick::Montage#filename(name)
910
+ Purpose: set filename value
911
+ */
912
+ VALUE
913
+ Montage_filename_eq(VALUE self, VALUE filename)
914
+ {
915
+ Montage *montage;
916
+
917
+ Data_Get_Struct(self, Montage, montage);
918
+ strncpy(montage->info->filename, STRING_PTR(filename), MaxTextExtent-1);
919
+ return self;
920
+ }
921
+
922
+ /*
923
+ Method: Magick::Montage#fill(color-name)
924
+ Purpose: set fill value
925
+ */
926
+ VALUE
927
+ Montage_fill_eq(VALUE self, VALUE color)
928
+ {
929
+ Montage *montage;
930
+
931
+ Data_Get_Struct(self, Montage, montage);
932
+ Color_to_PixelPacket(&montage->info->fill, color);
933
+ return self;
934
+ }
935
+
936
+ /*
937
+ Method: Magick::Montage#font(font-name)
938
+ Purpose: set font value
939
+ */
940
+ VALUE
941
+ Montage_font_eq(VALUE self, VALUE font)
942
+ {
943
+ Montage *montage;
944
+
945
+ Data_Get_Struct(self, Montage, montage);
946
+ magick_clone_string(&montage->info->font, STRING_PTR(font));
947
+
948
+ return self;
949
+ }
950
+
951
+ /*
952
+ Method: Magick::Montage#frame(frame-geometry)
953
+ Purpose: set frame value
954
+ Notes: The geometry is a string in the form:
955
+ <width>x<height>+<outer-bevel-width>+<inner-bevel-width>
956
+ or a Geometry object
957
+ */
958
+ VALUE
959
+ Montage_frame_eq(VALUE self, VALUE frame_arg)
960
+ {
961
+ Montage *montage;
962
+ volatile VALUE frame;
963
+
964
+ Data_Get_Struct(self, Montage, montage);
965
+ frame = rb_funcall(frame_arg, ID_to_s, 0);
966
+ magick_clone_string(&montage->info->frame, STRING_PTR(frame));
967
+
968
+ return self;
969
+ }
970
+
971
+ /*
972
+ Method: Magick::Montage#geometry(geometry)
973
+ Purpose: set geometry value
974
+ */
975
+ VALUE
976
+ Montage_geometry_eq(VALUE self, VALUE geometry_arg)
977
+ {
978
+ Montage *montage;
979
+ volatile VALUE geometry;
980
+
981
+ Data_Get_Struct(self, Montage, montage);
982
+ geometry = rb_funcall(geometry_arg, ID_to_s, 0);
983
+ magick_clone_string(&montage->info->geometry, STRING_PTR(geometry));
984
+
985
+ return self;
986
+ }
987
+
988
+ /*
989
+ Method: Magick::Montage#gravity(gravity-type)
990
+ Purpose: set gravity value
991
+ */
992
+ VALUE
993
+ Montage_gravity_eq(VALUE self, VALUE gravity)
994
+ {
995
+ Montage *montage;
996
+
997
+ Data_Get_Struct(self, Montage, montage);
998
+ VALUE_TO_ENUM(gravity, montage->info->gravity, GravityType);
999
+ return self;
1000
+ }
1001
+
1002
+ /*
1003
+ Method: Magick::Montage#initialize
1004
+ Purpose: Place-holder
1005
+ */
1006
+ VALUE
1007
+ Montage_initialize(VALUE self)
1008
+ {
1009
+ // Nothing to do!
1010
+ return self;
1011
+ }
1012
+
1013
+ /*
1014
+ Method: Magick::Montage#matte_color(color-name)
1015
+ Purpose: set matte_color value
1016
+ */
1017
+ VALUE
1018
+ Montage_matte_color_eq(VALUE self, VALUE color)
1019
+ {
1020
+ Montage *montage;
1021
+
1022
+ Data_Get_Struct(self, Montage, montage);
1023
+ Color_to_PixelPacket(&montage->info->matte_color, color);
1024
+ return self;
1025
+ }
1026
+
1027
+ /*
1028
+ Method: Montage.new
1029
+ Purpose: Create a new Montage object
1030
+ */
1031
+ VALUE
1032
+ #if defined(HAVE_RB_DEFINE_ALLOC_FUNC)
1033
+ Montage_alloc(VALUE class)
1034
+ #else
1035
+ Montage_new(VALUE class)
1036
+ #endif
1037
+ {
1038
+ MontageInfo *montage_info;
1039
+ Montage *montage;
1040
+ Info *image_info;
1041
+ volatile VALUE montage_obj;
1042
+
1043
+ // DO NOT call rm_info_new - we don't want to support an Info parm block.
1044
+ image_info = CloneImageInfo(NULL);
1045
+ if (!image_info)
1046
+ {
1047
+ rb_raise(rb_eNoMemError, "not enough memory to initialize Info object");
1048
+ }
1049
+
1050
+ montage_info = CloneMontageInfo(image_info, NULL);
1051
+ DestroyImageInfo(image_info);
1052
+
1053
+ if (!montage_info)
1054
+ {
1055
+ rb_raise(rb_eNoMemError, "not enough memory to initialize Magick::Montage object");
1056
+ }
1057
+
1058
+ montage = ALLOC(Montage);
1059
+ montage->info = montage_info;
1060
+ montage->compose = OverCompositeOp;
1061
+ montage_obj = Data_Wrap_Struct(class, NULL, destroy_Montage, montage);
1062
+
1063
+ #if !defined(HAVE_RB_DEFINE_ALLOC_FUNC)
1064
+ rb_obj_call_init(montage_obj, 0, NULL);
1065
+ #endif
1066
+
1067
+ return montage_obj;
1068
+ }
1069
+
1070
+ /*
1071
+ Extern: rm_montage_new()
1072
+ Purpose: Return a new Magick::Montage object
1073
+ */
1074
+
1075
+ VALUE rm_montage_new(void)
1076
+ {
1077
+ #if defined(HAVE_RB_DEFINE_ALLOC_FUNC)
1078
+ return Montage_initialize(Montage_alloc(Class_Montage));
1079
+ #else
1080
+ return Montage_new(Class_Montage);
1081
+ #endif
1082
+ }
1083
+
1084
+ /*
1085
+ Static: destroy_Montage
1086
+ Purpose: destory the MontageInfo struct and free the Montage struct
1087
+ Notes: if the Magick::Montage#texture method wrote a texture file,
1088
+ the file is deleted here.
1089
+ */
1090
+ static void
1091
+ destroy_Montage(void *obj)
1092
+ {
1093
+ Montage *montage = obj;
1094
+
1095
+ // If we saved a temporary texture image, delete it now.
1096
+ if (montage->info->texture != NULL)
1097
+ {
1098
+ rm_delete_temp_image(montage->info->texture);
1099
+ }
1100
+ DestroyMontageInfo(montage->info);
1101
+ xfree(montage);
1102
+ }
1103
+
1104
+ /*
1105
+ Method: Magick::Montage#pointsize=size
1106
+ Purpose: set pointsize value
1107
+ */
1108
+ VALUE
1109
+ Montage_pointsize_eq(VALUE self, VALUE size)
1110
+ {
1111
+ Montage *montage;
1112
+
1113
+ Data_Get_Struct(self, Montage, montage);
1114
+ montage->info->pointsize = NUM2DBL(size);
1115
+ return self;
1116
+ }
1117
+
1118
+ /*
1119
+ Method: Magick::Montage#shadow=shadow
1120
+ Purpose: set shadow value
1121
+ */
1122
+ VALUE
1123
+ Montage_shadow_eq(VALUE self, VALUE shadow)
1124
+ {
1125
+ Montage *montage;
1126
+
1127
+ Data_Get_Struct(self, Montage, montage);
1128
+ montage->info->shadow = RTEST(shadow);
1129
+ return self;
1130
+ }
1131
+
1132
+ /*
1133
+ Method: Magick::Montage#stroke(color-name)
1134
+ Purpose: set stroke value
1135
+ */
1136
+ VALUE
1137
+ Montage_stroke_eq(VALUE self, VALUE color)
1138
+ {
1139
+ Montage *montage;
1140
+
1141
+ Data_Get_Struct(self, Montage, montage);
1142
+ Color_to_PixelPacket(&montage->info->stroke, color);
1143
+ return self;
1144
+ }
1145
+
1146
+ /*
1147
+ Method: Montage#texture(texture-image)
1148
+ Purpose: set texture value
1149
+ */
1150
+ VALUE
1151
+ Montage_texture_eq(VALUE self, VALUE texture)
1152
+ {
1153
+ Montage *montage;
1154
+ Image *texture_image;
1155
+ char tmpnam[MaxTextExtent];
1156
+
1157
+ Data_Get_Struct(self, Montage, montage);
1158
+
1159
+ // If we had a previously defined temp texture image,
1160
+ // remove it now in preparation for this new one.
1161
+ if (montage->info->texture)
1162
+ {
1163
+ magick_free(montage->info->texture);
1164
+ montage->info->texture = NULL;
1165
+ }
1166
+
1167
+ Data_Get_Struct(ImageList_cur_image(texture), Image, texture_image);
1168
+
1169
+ // Write a temp copy of the image & save its name.
1170
+ rm_write_temp_image(texture_image, tmpnam);
1171
+ magick_clone_string(&montage->info->texture, tmpnam);
1172
+
1173
+ return self;
1174
+ }
1175
+
1176
+ /*
1177
+ Method: Magick::Montage#tile(tile)
1178
+ Purpose: set tile value
1179
+ */
1180
+ VALUE
1181
+ Montage_tile_eq(VALUE self, VALUE tile_arg)
1182
+ {
1183
+ Montage *montage;
1184
+ volatile VALUE tile;
1185
+
1186
+ Data_Get_Struct(self, Montage, montage);
1187
+ tile = rb_funcall(tile_arg, ID_to_s, 0);
1188
+ magick_clone_string(&montage->info->tile, STRING_PTR(tile));
1189
+
1190
+ return self;
1191
+ }
1192
+
1193
+ /*
1194
+ Method: Magick::Montage#title(title)
1195
+ Purpose: set title value
1196
+ */
1197
+ VALUE
1198
+ Montage_title_eq(VALUE self, VALUE title)
1199
+ {
1200
+ Montage *montage;
1201
+
1202
+ Data_Get_Struct(self, Montage, montage);
1203
+ magick_clone_string(&montage->info->title, STRING_PTR(title));
1204
+ return self;
1205
+ }
1206
+
1207
+
1208
+ static VALUE get_dummy_tm_img(VALUE klass)
1209
+ {
1210
+ volatile VALUE dummy_img = 0;
1211
+ Info *info;
1212
+ Image *image;
1213
+
1214
+ if (rb_cvar_defined(klass, ID__dummy_img_) != Qtrue)
1215
+ {
1216
+
1217
+ info = CloneImageInfo(NULL);
1218
+ if (!info)
1219
+ {
1220
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
1221
+ }
1222
+ image = AllocateImage(info);
1223
+ if (!image)
1224
+ {
1225
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
1226
+ }
1227
+ DestroyImageInfo(info);
1228
+ dummy_img = rm_image_new(image);
1229
+
1230
+ RUBY18(rb_cvar_set(klass, ID__dummy_img_, dummy_img, 0));
1231
+ RUBY16(rb_cvar_set(klass, ID__dummy_img_, dummy_img));
1232
+ }
1233
+ dummy_img = rb_cvar_get(klass, ID__dummy_img_);
1234
+
1235
+ return dummy_img;
1236
+ }
1237
+
1238
+
1239
+ /*
1240
+ * Static: get_type_metrics
1241
+ * Purpose: Call a get-type-metrics function
1242
+ * Notes: called by Draw_get_type_metrics and Draw_get_multiline_type_metrics
1243
+ */
1244
+ static VALUE
1245
+ get_type_metrics(
1246
+ int argc,
1247
+ VALUE *argv,
1248
+ VALUE self,
1249
+ get_type_metrics_func_t *getter)
1250
+ {
1251
+ static char attrs[] = "bcdefghiklmnopqrstuwxyz";
1252
+ #define ATTRS_L (sizeof(attrs)-1)
1253
+ Image *image;
1254
+ Draw *draw;
1255
+ TypeMetric metrics;
1256
+ char *text = NULL;
1257
+ long text_l;
1258
+ long x;
1259
+ unsigned int okay;
1260
+
1261
+ switch (argc)
1262
+ {
1263
+ case 1: // use default image
1264
+ text = STRING_PTR_LEN(argv[0], text_l);
1265
+
1266
+ for (x = 0; x < text_l; x++)
1267
+ {
1268
+ // Ensure text string doesn't refer to image attributes.
1269
+ if (text[x] == '%' && x < text_l-1)
1270
+ {
1271
+ int y;
1272
+ char spec = text[x+1];
1273
+
1274
+ for (y = 0; y < ATTRS_L; y++)
1275
+ {
1276
+ if (spec == attrs[y])
1277
+ {
1278
+ rb_raise(rb_eArgError,
1279
+ "text string contains image attribute reference `%%%c'",
1280
+ spec);
1281
+ }
1282
+ }
1283
+ }
1284
+ }
1285
+
1286
+ Data_Get_Struct(get_dummy_tm_img(CLASS_OF(self)), Image, image);
1287
+ break;
1288
+ case 2:
1289
+ Data_Get_Struct(ImageList_cur_image(argv[0]), Image, image);
1290
+ text = STRING_PTR(argv[1]);
1291
+ break; // okay
1292
+ default:
1293
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 2)", argc);
1294
+ break;
1295
+ }
1296
+
1297
+ Data_Get_Struct(self, Draw, draw);
1298
+ magick_clone_string(&draw->info->text, text);
1299
+
1300
+ okay = (*getter)(image, draw->info, &metrics);
1301
+
1302
+ if (!okay)
1303
+ {
1304
+ rb_warning("RMagick: get_type_metrics failed");
1305
+ return Qnil;
1306
+ }
1307
+ return TypeMetric_from_TypeMetric(&metrics);
1308
+ }