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
@@ -0,0 +1,740 @@
1
+ # $Id: misc.rb,v 1.17 2010/03/21 01:43:01 baror Exp $
2
+ # Copyright (C) 2009 Timothy P. Hunter
3
+ module Magick
4
+ class RVG
5
+
6
+ # This is a standard deep_copy method that is used in most classes.
7
+ # Thanks to Robert Klemme.
8
+ module Duplicatable
9
+
10
+ def deep_copy(h = {})
11
+ # Prevent recursion. If we reach the
12
+ # object we started with, stop copying.
13
+ copy = h[__id__]
14
+ unless copy
15
+ h[__id__] = copy = self.class.allocate
16
+ ivars = instance_variables
17
+ ivars.each do |ivar|
18
+ ivalue = instance_variable_get(ivar)
19
+ cvalue = case
20
+ when NilClass === ivalue, Symbol === ivalue, Float === ivalue,
21
+ Fixnum === ivalue, FalseClass === ivalue, TrueClass === ivalue
22
+ ivalue
23
+ when ivalue.respond_to?(:deep_copy)
24
+ ivalue.deep_copy(h)
25
+ when ivalue.respond_to?(:dup)
26
+ ivalue.dup
27
+ else
28
+ ivalue
29
+ end
30
+ copy.instance_variable_set(ivar, cvalue)
31
+ end
32
+ copy.freeze if frozen?
33
+ end
34
+ return copy
35
+ end
36
+
37
+ end # module Duplicatable
38
+
39
+
40
+ # Convert an array of method arguments to Float objects. If any
41
+ # cannot be converted, raise ArgumentError and issue a message.
42
+ def self.fmsg(*args)
43
+ "at least one argument cannot be converted to Float (got #{args.collect {|a| a.class}.join(', ')})"
44
+ end
45
+
46
+ def self.convert_to_float(*args)
47
+ allow_nil = false
48
+ if args.last == :allow_nil
49
+ allow_nil = true
50
+ args.pop
51
+ end
52
+ begin
53
+ fargs = args.collect { |a| (allow_nil && a.nil?) ? a : Float(a) }
54
+ rescue ArgumentError, TypeError
55
+ raise ArgumentError, self.fmsg(*args)
56
+ end
57
+ return fargs
58
+ end
59
+
60
+ def self.convert_one_to_float(arg)
61
+ begin
62
+ farg = Float(arg)
63
+ rescue ArgumentError, TypeError
64
+ raise ArgumentError, "argument cannot be converted to Float (got #{arg.class})"
65
+ end
66
+ return farg
67
+ end
68
+
69
+ end # class RVG
70
+ end # module Magick
71
+
72
+
73
+
74
+
75
+
76
+ module Magick
77
+ class RVG
78
+ class Utility
79
+
80
+ class TextStrategy
81
+
82
+ def initialize(context)
83
+ @ctx = context
84
+ @ctx.shadow.affine = @ctx.text_attrs.affine
85
+ end
86
+
87
+ def enquote(text)
88
+ if text.length > 2 && /\A(?:\"[^\"]+\"|\'[^\']+\'|\{[^\}]+\})\z/.match(text)
89
+ return text
90
+ elsif !text['\'']
91
+ text = '\''+text+'\''
92
+ return text
93
+ elsif !text['"']
94
+ text = '"'+text+'"'
95
+ return text
96
+ elsif !(text['{'] || text['}'])
97
+ text = '{'+text+'}'
98
+ return text
99
+ end
100
+
101
+ # escape existing braces, surround with braces
102
+ text.gsub!(/[}]/) { |b| '\\' + b }
103
+ return '{' + text + '}'
104
+ end
105
+
106
+ def glyph_metrics(glyph_orientation, glyph)
107
+ gm = @ctx.shadow.get_type_metrics("a" + glyph + "a")
108
+ gm2 = @ctx.shadow.get_type_metrics("aa")
109
+ h = (gm.ascent - gm.descent + 0.5 ).to_i
110
+ w = gm.width - gm2.width
111
+ if glyph_orientation == 0 || glyph_orientation == 180
112
+ [w, h]
113
+ else
114
+ [h, w]
115
+ end
116
+ end
117
+
118
+ def text_rel_coords(text)
119
+ y_rel_coords = []
120
+ x_rel_coords = []
121
+ first_word = true
122
+ words = text.split(::Magick::RVG::WORD_SEP)
123
+ words.each do |word|
124
+ unless first_word
125
+ wx, wy = get_word_spacing()
126
+ x_rel_coords << wx
127
+ y_rel_coords << wy
128
+ end
129
+ first_word = false
130
+ word.split('').each do |glyph|
131
+ wx, wy = get_letter_spacing(glyph)
132
+ x_rel_coords << wx
133
+ y_rel_coords << wy
134
+ end
135
+ end
136
+ [x_rel_coords, y_rel_coords]
137
+ end
138
+
139
+ def shift_baseline(glyph_orientation, glyph)
140
+ glyph_dimensions = @ctx.shadow.get_type_metrics(glyph)
141
+ if glyph_orientation == 0 || glyph_orientation == 180
142
+ x = glyph_dimensions.width
143
+ else
144
+ x = glyph_dimensions.ascent - glyph_dimensions.descent
145
+ end
146
+ case @ctx.text_attrs.baseline_shift
147
+ when :baseline
148
+ x = 0
149
+ when :sub
150
+ ;
151
+ when :super
152
+ x = -x
153
+ when /[-+]?(\d+)%/
154
+ m = $1 == '-' ? -1.0 : 1.0
155
+ x = (m * x * $1.to_f / 100.0)
156
+ else
157
+ x = -@ctx.text_attrs.baseline_shift
158
+ end
159
+ return x
160
+ end
161
+
162
+ def render_glyph(glyph_orientation, x, y, glyph)
163
+ if glyph_orientation == 0
164
+ @ctx.gc.text(x, y, enquote(glyph))
165
+ else
166
+ @ctx.gc.push
167
+ @ctx.gc.translate(x, y)
168
+ @ctx.gc.rotate(glyph_orientation)
169
+ @ctx.gc.translate(-x, -y)
170
+ @ctx.gc.text(x, y, enquote(glyph))
171
+ @ctx.gc.pop
172
+ end
173
+ end
174
+
175
+ end # class TextStrategy
176
+
177
+ class LRTextStrategy < TextStrategy
178
+
179
+ def get_word_spacing()
180
+ @word_space ||= glyph_metrics(@ctx.text_attrs.glyph_orientation_horizontal, ' ')[0]
181
+ [@word_space + @ctx.text_attrs.word_spacing, 0]
182
+ end
183
+
184
+ def get_letter_spacing(glyph)
185
+ gx, gy = glyph_metrics(@ctx.text_attrs.glyph_orientation_horizontal, glyph)
186
+ [gx+@ctx.text_attrs.letter_spacing, gy]
187
+ end
188
+
189
+ def render(x, y, text)
190
+ x_rel_coords, y_rel_coords = text_rel_coords(text)
191
+ dx = x_rel_coords.inject(0) {|sum, a| sum + a}
192
+ dy = y_rel_coords.max
193
+
194
+ # We're handling the anchoring.
195
+ @ctx.gc.push()
196
+ @ctx.gc.text_anchor(Magick::StartAnchor)
197
+ if @ctx.text_attrs.text_anchor == :end
198
+ x -= dx
199
+ elsif @ctx.text_attrs.text_anchor == :middle
200
+ x -= dx / 2
201
+ end
202
+
203
+ # Align the first glyph
204
+ case @ctx.text_attrs.glyph_orientation_horizontal
205
+ when 0
206
+ ;
207
+ when 90
208
+ y -= dy
209
+ when 180
210
+ x += x_rel_coords.shift
211
+ x_rel_coords << 0
212
+ y -= dy
213
+ when 270
214
+ x += x_rel_coords[0]
215
+ end
216
+
217
+ y += shift_baseline(@ctx.text_attrs.glyph_orientation_horizontal, text[0,1])
218
+
219
+ first_word = true
220
+ text.split(::Magick::RVG::WORD_SEP).each do |word|
221
+ unless first_word
222
+ x += x_rel_coords.shift
223
+ end
224
+ first_word = false
225
+ word.split('').each do |glyph|
226
+ render_glyph(@ctx.text_attrs.glyph_orientation_horizontal, x, y, glyph)
227
+ x += x_rel_coords.shift
228
+ end
229
+ end
230
+
231
+ @ctx.gc.pop()
232
+ [dx, 0]
233
+ end
234
+
235
+ end # class LRTextStrategy
236
+
237
+ class RLTextStrategy < TextStrategy
238
+
239
+ def render(x, y, text)
240
+ raise NotImplementedError
241
+ end
242
+
243
+ end # class RLTextStrategy
244
+
245
+
246
+ class TBTextStrategy < TextStrategy
247
+
248
+ def get_word_spacing()
249
+ @word_space ||= glyph_metrics(@ctx.text_attrs.glyph_orientation_vertical, ' ')[1]
250
+ [0, @word_space + @ctx.text_attrs.word_spacing]
251
+ end
252
+
253
+ def get_letter_spacing(glyph)
254
+ gx, gy = glyph_metrics(@ctx.text_attrs.glyph_orientation_vertical, glyph)
255
+ [gx, gy+@ctx.text_attrs.letter_spacing]
256
+ end
257
+
258
+ def render(x, y, text)
259
+ x_rel_coords, y_rel_coords = text_rel_coords(text)
260
+ dx = x_rel_coords.max
261
+ dy = y_rel_coords.inject(0) {|sum, a| sum + a}
262
+
263
+ # We're handling the anchoring.
264
+ @ctx.gc.push()
265
+ @ctx.gc.text_anchor(Magick::StartAnchor)
266
+ if @ctx.text_attrs.text_anchor == :end
267
+ y -= dy
268
+ elsif @ctx.text_attrs.text_anchor == :middle
269
+ y -= dy / 2
270
+ end
271
+
272
+ # Align the first glyph such that its center
273
+ # is aligned on x and its top is aligned on y.
274
+
275
+ case @ctx.text_attrs.glyph_orientation_vertical
276
+ when 0
277
+ x -= x_rel_coords.max / 2
278
+ y += y_rel_coords[0]
279
+ when 90
280
+ x -= x_rel_coords.max / 2
281
+ when 180
282
+ x += x_rel_coords.max / 2
283
+ when 270
284
+ x += x_rel_coords.max / 2
285
+ y += y_rel_coords.shift
286
+ y_rel_coords << 0 # since we used an element we need to add a dummy
287
+ end
288
+
289
+ x -= shift_baseline(@ctx.text_attrs.glyph_orientation_vertical, text[0,1])
290
+
291
+ first_word = true
292
+ text.split(::Magick::RVG::WORD_SEP).each do |word|
293
+ unless first_word
294
+ y += y_rel_coords.shift
295
+ x_rel_coords.shift
296
+ end
297
+ first_word = false
298
+ word.split('').each do |glyph|
299
+ case @ctx.text_attrs.glyph_orientation_vertical.to_i
300
+ when 0, 90, 270
301
+ x_shift = (dx - x_rel_coords.shift) / 2
302
+ when 180
303
+ x_shift = -(dx - x_rel_coords.shift) / 2
304
+ end
305
+
306
+ render_glyph(@ctx.text_attrs.glyph_orientation_vertical, x+x_shift, y, glyph)
307
+ y += y_rel_coords.shift
308
+ end
309
+ end
310
+
311
+ @ctx.gc.pop()
312
+ [0, dy]
313
+ end
314
+
315
+ end # class TBTextStrategy
316
+
317
+ # Handle "easy" text
318
+ class DefaultTextStrategy < TextStrategy
319
+
320
+ def render(x, y, text)
321
+ @ctx.gc.text(x, y, enquote(text))
322
+ tm = @ctx.shadow.get_type_metrics(text)
323
+ dx = case @ctx.text_attrs.text_anchor
324
+ when :start
325
+ tm.width
326
+ when :middle
327
+ tm.width / 2
328
+ when :end
329
+ 0
330
+ end
331
+ [dx, 0]
332
+ end
333
+
334
+ end # class NormalTextStrategy
335
+
336
+ end # class Utility
337
+ end # class RVG
338
+ end # module Magick
339
+
340
+
341
+
342
+
343
+ module Magick
344
+ class RVG
345
+ class Utility
346
+
347
+ class TextAttributes
348
+
349
+ public
350
+
351
+ WRITING_MODE = %w{lr-tb lr rl-tb rl tb-rl tb}
352
+
353
+ def initialize()
354
+ @affine = Array.new
355
+ @affine << Magick::AffineMatrix.new(1, 0, 0, 1, 0, 0)
356
+ @baseline_shift = Array.new
357
+ @baseline_shift << :baseline
358
+ @glyph_orientation_horizontal = Array.new
359
+ @glyph_orientation_horizontal << 0
360
+ @glyph_orientation_vertical = Array.new
361
+ @glyph_orientation_vertical << 90
362
+ @letter_spacing = Array.new
363
+ @letter_spacing << 0
364
+ @text_anchor = Array.new
365
+ @text_anchor << :start
366
+ @word_spacing = Array.new
367
+ @word_spacing << 0
368
+ @writing_mode = Array.new
369
+ @writing_mode << 'lr-tb'
370
+ end
371
+
372
+ def push()
373
+ @affine.push(@affine.last.dup)
374
+ @baseline_shift.push(@baseline_shift.last)
375
+ @text_anchor.push(@text_anchor.last)
376
+ @writing_mode.push(@writing_mode.last.dup)
377
+ @glyph_orientation_vertical.push(@glyph_orientation_vertical.last)
378
+ @glyph_orientation_horizontal.push(@glyph_orientation_horizontal.last)
379
+ @letter_spacing.push(@letter_spacing.last)
380
+ @word_spacing.push(@word_spacing.last)
381
+ end
382
+
383
+ def pop()
384
+ @affine.pop
385
+ @baseline_shift.pop
386
+ @text_anchor.pop
387
+ @writing_mode.pop
388
+ @glyph_orientation_vertical.pop
389
+ @glyph_orientation_horizontal.pop
390
+ @letter_spacing.pop
391
+ @word_spacing.pop
392
+ end
393
+
394
+ def set_affine(sx, rx, ry, sy, tx, ty)
395
+ @affine[-1].sx = sx
396
+ @affine[-1].rx = rx
397
+ @affine[-1].ry = ry
398
+ @affine[-1].sy = sy
399
+ @affine[-1].tx = tx
400
+ @affine[-1].ty = ty
401
+ end
402
+
403
+ def affine()
404
+ @affine[-1]
405
+ end
406
+
407
+ def baseline_shift()
408
+ @baseline_shift[-1]
409
+ end
410
+
411
+ def baseline_shift=(value)
412
+ @baseline_shift[-1] = value
413
+ end
414
+
415
+ def text_anchor()
416
+ @text_anchor[-1]
417
+ end
418
+
419
+ def text_anchor=(anchor)
420
+ @text_anchor[-1] = anchor
421
+ end
422
+
423
+ def glyph_orientation_vertical()
424
+ @glyph_orientation_vertical[-1]
425
+ end
426
+
427
+ def glyph_orientation_vertical=(angle)
428
+ @glyph_orientation_vertical[-1] = angle
429
+ end
430
+
431
+ def glyph_orientation_horizontal()
432
+ @glyph_orientation_horizontal[-1]
433
+ end
434
+
435
+ def glyph_orientation_horizontal=(angle)
436
+ @glyph_orientation_horizontal[-1] = angle
437
+ end
438
+
439
+ def letter_spacing()
440
+ @letter_spacing[-1]
441
+ end
442
+
443
+ def letter_spacing=(value)
444
+ @letter_spacing[-1] = value
445
+ end
446
+
447
+ def non_default?
448
+ @baseline_shift[-1] != :baseline || @letter_spacing[-1] != 0 ||
449
+ @word_spacing[-1] != 0 || @writing_mode[-1][/\Alr/].nil? ||
450
+ @glyph_orientation_horizontal[-1] != 0
451
+ end
452
+
453
+ def word_spacing()
454
+ @word_spacing[-1]
455
+ end
456
+
457
+ def word_spacing=(value)
458
+ @word_spacing[-1] = value
459
+ end
460
+
461
+ def writing_mode()
462
+ @writing_mode[-1]
463
+ end
464
+
465
+ def writing_mode=(mode)
466
+ @writing_mode[-1] = WRITING_MODE.include?(mode) ? mode : 'lr-tb'
467
+ end
468
+
469
+ end # class TextAttributes
470
+
471
+ class GraphicContext
472
+
473
+ FONT_STRETCH = {:normal => Magick::NormalStretch,
474
+ :ultra_condensed => Magick::UltraCondensedStretch,
475
+ :extra_condensed => Magick::ExtraCondensedStretch,
476
+ :condensed => Magick::CondensedStretch,
477
+ :semi_condensed => Magick::SemiCondensedStretch,
478
+ :semi_expanded => Magick::SemiExpandedStretch,
479
+ :expanded => Magick::ExpandedStretch,
480
+ :extra_expanded => Magick::ExtraExpandedStretch,
481
+ :ultra_expanded => Magick::UltraExpandedStretch}
482
+
483
+ FONT_STYLE = {:normal => Magick::NormalStyle,
484
+ :italic => Magick::ItalicStyle,
485
+ :oblique => Magick::ObliqueStyle}
486
+
487
+ FONT_WEIGHT = {'normal' => Magick::NormalWeight,
488
+ 'bold' => Magick::BoldWeight,
489
+ 'bolder' => Magick::BolderWeight,
490
+ 'lighter' => Magick::LighterWeight}
491
+
492
+ TEXT_ANCHOR = {:start => Magick::StartAnchor,
493
+ :middle => Magick::MiddleAnchor,
494
+ :end => Magick::EndAnchor}
495
+
496
+ ANCHOR_TO_ALIGN = {:start => Magick::LeftAlign,
497
+ :middle => Magick::CenterAlign,
498
+ :end => Magick::RightAlign}
499
+
500
+ TEXT_DECORATION = {:none => Magick::NoDecoration,
501
+ :underline => Magick::UnderlineDecoration,
502
+ :overline => Magick::OverlineDecoration,
503
+ :line_through => Magick::LineThroughDecoration}
504
+
505
+ TEXT_STRATEGIES = {'lr-tb'=>LRTextStrategy, 'lr'=>LRTextStrategy,
506
+ 'rt-tb'=>RLTextStrategy, 'rl'=>RLTextStrategy,
507
+ 'tb-rl'=>TBTextStrategy, 'tb'=>TBTextStrategy}
508
+
509
+ def GraphicContext.degrees_to_radians(deg)
510
+ Math::PI * (deg % 360.0) / 180.0
511
+ end
512
+
513
+ private
514
+
515
+ def init_matrix()
516
+ @rx = @ry = 0
517
+ @sx = @sy = 1
518
+ @tx = @ty = 0
519
+ end
520
+
521
+ def concat_matrix()
522
+ curr = @text_attrs.affine
523
+ sx = curr.sx * @sx + curr.ry * @rx
524
+ rx = curr.rx * @sx + curr.sy * @rx
525
+ ry = curr.sx * @ry + curr.ry * @sy
526
+ sy = curr.rx * @ry + curr.sy * @sy
527
+ tx = curr.sx * @tx + curr.ry * @ty + curr.tx
528
+ ty = curr.rx * @tx + curr.sy * @ty + curr.ty
529
+ @text_attrs.set_affine(sx, rx, ry, sy, tx, ty)
530
+ init_matrix()
531
+ end
532
+
533
+ public
534
+
535
+ attr_reader :gc, :text_attrs
536
+
537
+ def initialize()
538
+ @gc = Magick::Draw.new
539
+ @shadow = Array.new
540
+ @shadow << Magick::Draw.new
541
+ @text_attrs = TextAttributes.new
542
+ init_matrix()
543
+ end
544
+
545
+ def method_missing(methID, *args, &block)
546
+ @gc.__send__(methID, *args, &block)
547
+ end
548
+
549
+ def affine(sx, rx, ry, sy, tx, ty)
550
+ sx, rx, ry, sy, tx, ty = Magick::RVG.convert_to_float(sx, rx, ry, sy, tx, ty)
551
+ @gc.affine(sx, rx, ry, sy, tx, ty)
552
+ @text_attrs.set_affine(sx, rx, ry, sy, tx, ty)
553
+ nil
554
+ end
555
+
556
+ def baseline_shift(value)
557
+ @text_attrs.baseline_shift = case value
558
+ when 'baseline', 'sub', 'super'
559
+ value.intern
560
+ when /[-+]?\d+%/, Numeric
561
+ value
562
+ else
563
+ :baseline
564
+ end
565
+ nil
566
+ end
567
+
568
+ def font(name)
569
+ @gc.font(name)
570
+ @shadow[-1].font = name
571
+ nil
572
+ end
573
+
574
+ def font_family(name)
575
+ @gc.font_family(name)
576
+ @shadow[-1].font_family = name
577
+ nil
578
+ end
579
+
580
+ def font_size(points)
581
+ @gc.font_size(points)
582
+ @shadow[-1].pointsize = points
583
+ nil
584
+ end
585
+
586
+ def font_stretch(stretch)
587
+ stretch = FONT_STRETCH.fetch(stretch.intern, Magick::NormalStretch)
588
+ @gc.font_stretch(stretch)
589
+ @shadow[-1].font_stretch = stretch
590
+ nil
591
+ end
592
+
593
+ def font_style(style)
594
+ style = FONT_STYLE.fetch(style.intern, Magick::NormalStyle)
595
+ @gc.font_style(style)
596
+ @shadow[-1].font_style = style
597
+ nil
598
+ end
599
+
600
+ def font_weight(weight)
601
+ # If the arg is not in the hash use it directly. Handles numeric values.
602
+ weight = FONT_WEIGHT.fetch(weight) {|key| key}
603
+ @gc.font_weight(weight)
604
+ @shadow[-1].font_weight = weight
605
+ nil
606
+ end
607
+
608
+ def glyph_orientation_horizontal(deg)
609
+ deg = Magick::RVG.convert_one_to_float(deg)
610
+ @text_attrs.glyph_orientation_horizontal = (deg % 360) / 90 * 90
611
+ nil
612
+ end
613
+
614
+ def glyph_orientation_vertical(deg)
615
+ deg = Magick::RVG.convert_one_to_float(deg)
616
+ @text_attrs.glyph_orientation_vertical = (deg % 360) / 90 * 90
617
+ nil
618
+ end
619
+
620
+ def inspect()
621
+ @gc.inspect
622
+ end
623
+
624
+ def letter_spacing(value)
625
+ @text_attrs.letter_spacing = Magick::RVG.convert_one_to_float(value)
626
+ nil
627
+ end
628
+
629
+ def push()
630
+ @gc.push
631
+ @shadow.push(@shadow.last.dup)
632
+ @text_attrs.push
633
+ nil
634
+ end
635
+
636
+ def pop()
637
+ @gc.pop
638
+ @shadow.pop
639
+ @text_attrs.pop
640
+ nil
641
+ end
642
+
643
+ def rotate(degrees)
644
+ degrees = Magick::RVG.convert_one_to_float(degrees)
645
+ @gc.rotate(degrees)
646
+ @sx = Math.cos(GraphicContext.degrees_to_radians(degrees))
647
+ @rx = Math.sin(GraphicContext.degrees_to_radians(degrees))
648
+ @ry = -Math.sin(GraphicContext.degrees_to_radians(degrees))
649
+ @sy = Math.cos(GraphicContext.degrees_to_radians(degrees))
650
+ concat_matrix()
651
+ nil
652
+ end
653
+
654
+ def scale(sx, sy)
655
+ sx, sy = Magick::RVG.convert_to_float(sx, sy)
656
+ @gc.scale(sx, sy)
657
+ @sx, @sy = sx, sy
658
+ concat_matrix()
659
+ nil
660
+ end
661
+
662
+ def shadow()
663
+ @shadow.last
664
+ end
665
+
666
+ def skewX(degrees)
667
+ degrees = Magick::RVG.convert_one_to_float(degrees)
668
+ @gc.skewX(degrees)
669
+ @ry = Math.tan(GraphicContext.degrees_to_radians(degrees))
670
+ concat_matrix()
671
+ nil
672
+ end
673
+
674
+ def skewY(degrees)
675
+ degrees = Magick::RVG.convert_one_to_float(degrees)
676
+ @gc.skewY(degrees)
677
+ @rx = Math.tan(GraphicContext.degrees_to_radians(degrees))
678
+ concat_matrix()
679
+ nil
680
+ end
681
+
682
+ def stroke_width(width)
683
+ width = Magick::RVG.convert_one_to_float(width)
684
+ @gc.stroke_width(width)
685
+ @shadow[-1].stroke_width = width
686
+ nil
687
+ end
688
+
689
+ def text(x, y, text)
690
+ return if text.length == 0
691
+ if @text_attrs.non_default?
692
+ text_renderer = TEXT_STRATEGIES[@text_attrs.writing_mode].new(self)
693
+ else
694
+ text_renderer = DefaultTextStrategy.new(self)
695
+ end
696
+
697
+ return text_renderer.render(x, y, text)
698
+ end
699
+
700
+ def text_anchor(anchor)
701
+ anchor = anchor.intern
702
+ anchor_enum = TEXT_ANCHOR.fetch(anchor, Magick::StartAnchor)
703
+ @gc.text_anchor(anchor_enum)
704
+ align = ANCHOR_TO_ALIGN.fetch(anchor, Magick::LeftAlign)
705
+ @shadow[-1].align = align
706
+ @text_attrs.text_anchor = anchor
707
+ nil
708
+ end
709
+
710
+ def text_decoration(decoration)
711
+ decoration = TEXT_DECORATION.fetch(decoration.intern, Magick::NoDecoration)
712
+ @gc.decorate(decoration)
713
+ @shadow[-1].decorate = decoration
714
+ nil
715
+ end
716
+
717
+ def translate(tx, ty)
718
+ tx, ty = Magick::RVG.convert_to_float(tx, ty)
719
+ @gc.translate(tx, ty)
720
+ @tx, @ty = tx, ty
721
+ concat_matrix()
722
+ nil
723
+ end
724
+
725
+ def word_spacing(value)
726
+ @text_attrs.word_spacing = Magick::RVG.convert_one_to_float(value)
727
+ nil
728
+ end
729
+
730
+ def writing_mode(mode)
731
+ @text_attrs.writing_mode = mode
732
+ nil
733
+ end
734
+
735
+ end # class GraphicContext
736
+
737
+ end # class Utility
738
+ end # class RVG
739
+ end # module Magick
740
+