rmagick4j 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. data/History.txt +84 -0
  2. data/LICENSE.txt +9 -0
  3. data/Manifest.txt +142 -0
  4. data/README.txt +25 -0
  5. data/Rakefile +109 -0
  6. data/lib/RMagick.rb +1861 -0
  7. data/lib/jhlabs-filters.jar +0 -0
  8. data/lib/magick4j.jar +0 -0
  9. data/lib/rmagick4j/constants.rb +21 -0
  10. data/lib/rmagick4j/draw.rb +86 -0
  11. data/lib/rmagick4j/enum.rb +120 -0
  12. data/lib/rmagick4j/gradient_fill.rb +14 -0
  13. data/lib/rmagick4j/image.rb +289 -0
  14. data/lib/rmagick4j/image_list.rb +21 -0
  15. data/lib/rmagick4j/pixel.rb +170 -0
  16. data/lib/rmagick4j/rmagick4j.rb +19 -0
  17. data/lib/rmagick4j/texture_fill.rb +14 -0
  18. data/lib/rmagick4j/type_metric.rb +8 -0
  19. data/lib/rmagick4j/version.rb +5 -0
  20. data/lib/rvg/clippath.rb +48 -0
  21. data/lib/rvg/container.rb +131 -0
  22. data/lib/rvg/deep_equal.rb +56 -0
  23. data/lib/rvg/describable.rb +53 -0
  24. data/lib/rvg/embellishable.rb +417 -0
  25. data/lib/rvg/misc.rb +739 -0
  26. data/lib/rvg/paint.rb +55 -0
  27. data/lib/rvg/pathdata.rb +131 -0
  28. data/lib/rvg/rvg.rb +283 -0
  29. data/lib/rvg/stretchable.rb +168 -0
  30. data/lib/rvg/stylable.rb +118 -0
  31. data/lib/rvg/text.rb +187 -0
  32. data/lib/rvg/transformable.rb +133 -0
  33. data/lib/rvg/units.rb +66 -0
  34. data/lib/svgsalamander.jar +0 -0
  35. data/test/RMagickTestSuite.rb +129 -0
  36. data/test/eyetests/bullseye.rb +150 -0
  37. data/test/eyetests/tests/draw_arc_basic.rb +16 -0
  38. data/test/eyetests/tests/draw_circle_affine.rb +19 -0
  39. data/test/eyetests/tests/draw_circle_basic.rb +16 -0
  40. data/test/eyetests/tests/draw_ellipse_affine.rb +19 -0
  41. data/test/eyetests/tests/draw_ellipse_basic.rb +16 -0
  42. data/test/eyetests/tests/draw_line_affine.rb +24 -0
  43. data/test/eyetests/tests/draw_line_basic.rb +20 -0
  44. data/test/eyetests/tests/draw_pattern_1.rb +35 -0
  45. data/test/eyetests/tests/draw_polygon_affine.rb +21 -0
  46. data/test/eyetests/tests/draw_polygon_basic.rb +19 -0
  47. data/test/eyetests/tests/draw_polyline_affine.rb +19 -0
  48. data/test/eyetests/tests/draw_polyline_basic.rb +18 -0
  49. data/test/eyetests/tests/draw_rectangle_affine.rb +16 -0
  50. data/test/eyetests/tests/draw_rectangle_basic.rb +16 -0
  51. data/test/eyetests/tests/draw_rmagick_test_01.rb +35 -0
  52. data/test/eyetests/tests/draw_rmagick_test_02.rb +40 -0
  53. data/test/eyetests/tests/draw_rmagick_test_03.rb +17 -0
  54. data/test/eyetests/tests/draw_rmagick_test_04.rb +21 -0
  55. data/test/eyetests/tests/draw_roundrectangle_affine.rb +19 -0
  56. data/test/eyetests/tests/draw_roundrectangle_basic.rb +16 -0
  57. data/test/eyetests/tests/gradient_fill_horizontal_diagonal_fill.rb +9 -0
  58. data/test/eyetests/tests/gradient_fill_horizontal_fill.rb +9 -0
  59. data/test/eyetests/tests/gradient_fill_point_fill.rb +9 -0
  60. data/test/eyetests/tests/gradient_fill_vertical_diagonal_fill.rb +9 -0
  61. data/test/eyetests/tests/gradient_fill_vertical_fill.rb +9 -0
  62. data/test/eyetests/tests/gruff_accumulator_bar.rb +29 -0
  63. data/test/eyetests/tests/gruff_area_1.rb +16 -0
  64. data/test/eyetests/tests/gruff_area_2.rb +27 -0
  65. data/test/eyetests/tests/gruff_bar_1.rb +29 -0
  66. data/test/eyetests/tests/gruff_bar_2.rb +19 -0
  67. data/test/eyetests/tests/gruff_line_1.rb +13 -0
  68. data/test/eyetests/tests/gruff_line_2.rb +20 -0
  69. data/test/eyetests/tests/gruff_net_1.rb +16 -0
  70. data/test/eyetests/tests/gruff_net_2.rb +16 -0
  71. data/test/eyetests/tests/gruff_pie_1.rb +21 -0
  72. data/test/eyetests/tests/gruff_pie_2.rb +22 -0
  73. data/test/eyetests/tests/gruff_scene_1.rb +14 -0
  74. data/test/eyetests/tests/gruff_scene_2.rb +14 -0
  75. data/test/eyetests/tests/gruff_sidebar.rb +32 -0
  76. data/test/eyetests/tests/gruff_sidestacked_bar_1.rb +26 -0
  77. data/test/eyetests/tests/gruff_sidestacked_bar_2.rb +26 -0
  78. data/test/eyetests/tests/gruff_spider_1.rb +22 -0
  79. data/test/eyetests/tests/gruff_spider_2.rb +15 -0
  80. data/test/eyetests/tests/gruff_stacked_bar_1.rb +23 -0
  81. data/test/eyetests/tests/gruff_stacked_bar_2.rb +26 -0
  82. data/test/eyetests/tests/hatch_fill.rb +9 -0
  83. data/test/eyetests/tests/image_list_flatten_images.rb +15 -0
  84. data/test/eyetests/tests/new_image.rb +24 -0
  85. data/test/eyetests/tests/path_a_command_01.rb +16 -0
  86. data/test/eyetests/tests/path_a_command_02.rb +19 -0
  87. data/test/eyetests/tests/path_c_command_01.rb +16 -0
  88. data/test/eyetests/tests/path_c_command_02.rb +16 -0
  89. data/test/eyetests/tests/path_complex_01.rb +16 -0
  90. data/test/eyetests/tests/path_espiral_01.rb +28 -0
  91. data/test/eyetests/tests/path_h_command_01.rb +16 -0
  92. data/test/eyetests/tests/path_h_command_02.rb +16 -0
  93. data/test/eyetests/tests/path_l_command_01.rb +16 -0
  94. data/test/eyetests/tests/path_l_command_02.rb +16 -0
  95. data/test/eyetests/tests/path_m_command_01.rb +16 -0
  96. data/test/eyetests/tests/path_m_command_02.rb +16 -0
  97. data/test/eyetests/tests/path_m_command_03.rb +16 -0
  98. data/test/eyetests/tests/path_q_command_01.rb +16 -0
  99. data/test/eyetests/tests/path_q_command_02.rb +16 -0
  100. data/test/eyetests/tests/path_q_command_03.rb +25 -0
  101. data/test/eyetests/tests/path_s_command_01.rb +16 -0
  102. data/test/eyetests/tests/path_s_command_02.rb +16 -0
  103. data/test/eyetests/tests/path_star_01.rb +16 -0
  104. data/test/eyetests/tests/path_t_command_01.rb +16 -0
  105. data/test/eyetests/tests/path_t_command_02.rb +16 -0
  106. data/test/eyetests/tests/path_v_command_01.rb +16 -0
  107. data/test/eyetests/tests/path_v_command_02.rb +16 -0
  108. data/test/eyetests/tests/store_pixel_smiley.rb +123 -0
  109. data/test/eyetests/tests/texture_fill.rb +11 -0
  110. data/test/gruff_tests/test/gruff_test_case.rb +120 -0
  111. data/test/gruff_tests/test/monkey_gruff.rb +7 -0
  112. data/test/gruff_tests/test/test_accumulator_bar.rb +50 -0
  113. data/test/gruff_tests/test/test_area.rb +134 -0
  114. data/test/gruff_tests/test/test_bar.rb +283 -0
  115. data/test/gruff_tests/test/test_base.rb +8 -0
  116. data/test/gruff_tests/test/test_bullet.rb +26 -0
  117. data/test/gruff_tests/test/test_legend.rb +71 -0
  118. data/test/gruff_tests/test/test_line.rb +493 -0
  119. data/test/gruff_tests/test/test_mini_bar.rb +32 -0
  120. data/test/gruff_tests/test/test_mini_pie.rb +20 -0
  121. data/test/gruff_tests/test/test_mini_side_bar.rb +37 -0
  122. data/test/gruff_tests/test/test_net.rb +230 -0
  123. data/test/gruff_tests/test/test_photo.rb +41 -0
  124. data/test/gruff_tests/test/test_pie.rb +154 -0
  125. data/test/gruff_tests/test/test_scene.rb +100 -0
  126. data/test/gruff_tests/test/test_side_bar.rb +12 -0
  127. data/test/gruff_tests/test/test_sidestacked_bar.rb +89 -0
  128. data/test/gruff_tests/test/test_spider.rb +216 -0
  129. data/test/gruff_tests/test/test_stacked_bar.rb +52 -0
  130. data/test/images/clown.jpg +0 -0
  131. data/test/images/texture.jpg +0 -0
  132. data/test/implemented_methods.rb +18 -0
  133. data/test/spec/draw_spec.rb +24 -0
  134. data/test/spec/image_constants.rb +76 -0
  135. data/test/spec/image_spec.rb +23 -0
  136. data/test/spec/pixel_spec.rb +84 -0
  137. data/test/spec/stories/geometry_runner.rb +13 -0
  138. data/test/spec/stories/geometry_steps.rb +24 -0
  139. data/test/spec/stories/geometry_story.rb +116 -0
  140. data/test/spec/stories/image_filling_runner.rb +13 -0
  141. data/test/spec/stories/image_filling_steps.rb +64 -0
  142. data/test/spec/stories/image_filling_story.rb +41 -0
  143. metadata +215 -0
@@ -0,0 +1,21 @@
1
+
2
+ module Magick
3
+
4
+ class ImageList < Array
5
+
6
+ def flatten_images
7
+ img = @images.map { |obj| obj._image }
8
+
9
+ image = img.inject do |memo, obj|
10
+ memo.flatten(obj)
11
+ end
12
+
13
+ Image.from_image(image)
14
+ end
15
+
16
+ def to_blob(&add)
17
+ # TODO Support lists.
18
+ first.to_blob(&add)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,170 @@
1
+ require 'observer'
2
+
3
+ module Magick
4
+ Pixel = Magick4J::PixelPacket
5
+
6
+ class Pixel
7
+ include Comparable
8
+ include Observable
9
+
10
+ alias_method :to_java_color, :to_color
11
+ alias_method :to_color, :to_string
12
+
13
+ def type_check(value, conversion, typename)
14
+ unless value.respond_to? conversion
15
+ raise TypeError.new "can't convert #{value.class.name} into #{typename}"
16
+ end
17
+ value.send(conversion)
18
+ end
19
+
20
+ def initialize(red=0, green=0, blue=0, opacity=0)
21
+ # TODO: I think PixelPacket should be int-based (Pixel requires argument
22
+ # conversion, but PixelPacket requires us to reconvert to double (see
23
+ # to_f below). This is a bunch of work.
24
+ red = type_check(red, :to_int, "Integer")
25
+ green = type_check(green, :to_int, "Integer")
26
+ blue = type_check(blue, :to_int, "Integer")
27
+ opacity = type_check(opacity, :to_int, "Integer")
28
+
29
+ # TODO: Add support to CMYKColorspace.
30
+ super(red, green, blue, opacity)
31
+ end
32
+
33
+ def self.from_color(color_name)
34
+ result = Magick4J::ColorDatabase.lookUp(color_name)
35
+ raise ArgumentError, "invalid color name: #{color_name}" if result.nil?
36
+ result
37
+ end
38
+
39
+ def self.from_HSL(array)
40
+ raise ArgumentError, 'array argument must have at least 3 elements' if array.size < 3
41
+ # It can't be 'hue, saturation, lightness = array' because array length
42
+ # can be greater than 3.
43
+ hue, saturation, lightness = array[0], array[1], array[2]
44
+ r, g, b = if saturation == 0
45
+ 3*[[[0, QuantumRange*lightness].max, QuantumRange].min.floor.to_i]
46
+ else
47
+ m2 = if lightness <= 0.5
48
+ lightness*(saturation + 1.0)
49
+ else
50
+ lightness + saturation - (lightness*saturation)
51
+ end
52
+ m1 = 2.0*lightness - m2
53
+
54
+ [
55
+ [[0, QuantumRange*from_hue(m1, m2, hue+1.0/3.0)].max, QuantumRange].min.floor.to_i,
56
+ [[0, QuantumRange*from_hue(m1, m2, hue)].max, QuantumRange].min.floor.to_i,
57
+ [[0, QuantumRange*from_hue(m1, m2, hue-1.0/3.0)].max, QuantumRange].min.floor.to_i
58
+ ]
59
+ end
60
+ Pixel.new(r, g, b)
61
+ end
62
+
63
+ def eql?(other)
64
+ (self <=> other) == 0
65
+ end
66
+
67
+ def <=>(pixel)
68
+ # Alphabetical algorithm.
69
+ if red != pixel.red
70
+ red <=> pixel.red
71
+ elsif green != pixel.green
72
+ green <=> pixel.green
73
+ elsif blue == pixel.blue
74
+ blue <=> pixel.blue
75
+ elsif opacity != pixel.opacity
76
+ opacity <=> pixel.opacity
77
+ else
78
+ # Enebo: I added as a last test in conditional (is this needed? test?)
79
+ # Serabe: In fact, I don't know, but it is the way RMagick does it.
80
+ self.class <=> pixel.class
81
+ end
82
+ end
83
+
84
+ alias_method :yellow, :blue
85
+ alias_method :yellow=, :blue=
86
+
87
+ # TODO: Hook colorspace into this method
88
+ # Extracted from color.c:1698
89
+ def fcmp(pixel, fuzz=0.0, colorspace=nil)
90
+ raise TypeError.new("wrong argument type #{pixel.class.name} (expected Data)") unless pixel.kind_of? Pixel
91
+ raise TypeError.new("") unless fuzz.kind_of? Numeric
92
+ if colorspace and !colorspace.kind_of? ::Magick::ColorspaceType
93
+ raise TypeError.new("Not a colorspace")
94
+ end
95
+
96
+ fuzz = 3.0*([fuzz.to_f, 0.7071067811865475244008443621048490].max**2)
97
+
98
+ # TODO: How does matte affect this algorithm?
99
+
100
+ distance = (red-pixel.red)**2
101
+ return false if distance > fuzz
102
+ distance += (green-pixel.green)**2
103
+ return false if distance > fuzz
104
+ distance += (blue-pixel.blue)**2
105
+ return false if distance > fuzz
106
+ true #The colors are similar!!!
107
+ end
108
+
109
+ alias_method :magenta, :green
110
+ alias_method :magenta=, :green=
111
+
112
+ # Thanks, FSM, for the RMagick documentation.
113
+ def intensity
114
+ 0.299*red+0.587*green+0.114*blue
115
+ end
116
+
117
+ alias_method :black, :opacity
118
+ alias_method :black=, :opacity=
119
+
120
+ alias_method :cyan, :red
121
+ alias_method :cyan=, :red=
122
+
123
+ # Extracted from gem.c:429
124
+ def to_HSL
125
+ r, g, b = QuantumScale*red, QuantumScale*green, QuantumScale*blue
126
+ max = [r, g, b].max
127
+ min = [r, g, b].min
128
+ lightness = (min+max)/2.0
129
+ delta = max - min
130
+ if(delta == 0.0)
131
+ hue, saturation = 0.0, 0.0
132
+ else
133
+ saturation = if lightness <0.5
134
+ delta /(min+max)
135
+ else
136
+ delta / (2.0-(min+max))
137
+ end
138
+ hue = if r == max
139
+ calculate_hue(b, g, max, delta)
140
+ elsif g == max
141
+ (1.0/3.0) + calculate_hue(r, b, max, delta)
142
+ elsif b == max
143
+ (2.0/3.0)+calculate_hue(g, r, max, delta)
144
+ end
145
+ if hue < 0.0
146
+ hue += 1.0
147
+ elsif hue > 1.0
148
+ hue -= 1.0
149
+ end
150
+ end
151
+ [hue, saturation, lightness]
152
+ end
153
+
154
+ private
155
+
156
+ def calculate_hue(val1, val2, max, delta)
157
+ (( ((max-val1)/6.0)+ (delta/2.0))- (((max-val2)/6.0)+(delta/2.0)))/delta
158
+ end
159
+
160
+ def from_hue(m1, m2, hue)
161
+ hue += 1.0 if hue < 0.0
162
+ hue -= 1.0 if hue > 1.0
163
+
164
+ return m1+6.0*(m2-m1)*hue if (6.0*hue) < 1.0
165
+ return m2 if (2.0*hue) < 1.0
166
+ return m1+6.0*(m2-m1)*(2.0/3.0-hue) if (3.0*hue) < 2.0
167
+ m1
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,19 @@
1
+ require 'java'
2
+
3
+ rmagick4j_dir = File.dirname(__FILE__)
4
+
5
+ # TODO See about using Raven to get gems of jhlabs and svgsalamander?
6
+ require File.join(rmagick4j_dir, '..', 'jhlabs-filters.jar')
7
+ require File.join(rmagick4j_dir, '..', 'magick4j.jar')
8
+ require File.join(rmagick4j_dir, '..', 'svgsalamander.jar')
9
+
10
+ #RMagick classes, keep in alphabetical order, please.
11
+ require File.join(rmagick4j_dir, 'constants')
12
+ require File.join(rmagick4j_dir, 'draw')
13
+ require File.join(rmagick4j_dir, 'enum')
14
+ require File.join(rmagick4j_dir, 'gradient_fill')
15
+ require File.join(rmagick4j_dir, 'image')
16
+ require File.join(rmagick4j_dir, 'image_list')
17
+ require File.join(rmagick4j_dir, 'pixel')
18
+ require File.join(rmagick4j_dir, 'texture_fill')
19
+ require File.join(rmagick4j_dir, 'type_metric')
@@ -0,0 +1,14 @@
1
+
2
+ module Magick
3
+ class TextureFill
4
+
5
+ def fill(image)
6
+ @fill.fill(image._image)
7
+ end
8
+
9
+ def initialize(image)
10
+ image = image.cur_image if image.respond_to? :cur_image
11
+ @fill = Magick4J.TextureFill.new(image._image)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,8 @@
1
+
2
+ module Magick
3
+ class TypeMetric
4
+
5
+ attr_accessor :ascent, :descent, :height, :max_advance, :width
6
+
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ module RMagick4J
2
+ module Version
3
+ VERSION = "0.3.5"
4
+ end
5
+ end
@@ -0,0 +1,48 @@
1
+ #--
2
+ # $Id: clippath.rb,v 1.4 2008/02/24 18:26:36 rmagick Exp $
3
+ # Copyright (C) 2008 Timothy P. Hunter
4
+ #++
5
+ module Magick
6
+ class RVG
7
+
8
+ class ClipPath
9
+ include ShapeConstructors
10
+ include UseConstructors
11
+ include TextConstructors
12
+ include Describable
13
+ include Stylable
14
+ include Duplicatable
15
+
16
+ # Create a clipping path. Within the block create an outline
17
+ # from one or more paths, basic shapes, text objects, or +use+.
18
+ # Everything drawn within the outline will be displayed.
19
+ # Anything drawn outside the outline will not.
20
+ #
21
+ # If the clipping path contains a +use+, it
22
+ # must directly reference path, basic shape, or text objects.
23
+ #
24
+ # Attach the clipping path to an object with the :clip_path style.
25
+ def initialize(clip_path_units='userSpaceOnUse')
26
+ super()
27
+ if ! ['userSpaceOnUse', 'objectBoundingBox'].include?(clip_path_units)
28
+ raise ArgumentError, "undefined value for clip path units: #{clip_path_units}"
29
+ end
30
+ @clip_path_units = clip_path_units
31
+ @content = Content.new
32
+ yield(self) if block_given?
33
+ end
34
+
35
+ def add_primitives(gc, style) #:nodoc:
36
+ name = __id__.to_s
37
+ gc.define_clip_path(name) do
38
+ gc.clip_units(@clip_path_units)
39
+ @content.each { |element| element.add_primitives(gc) }
40
+ end
41
+ gc.clip_path(name)
42
+ end
43
+
44
+ end # class ClipPath
45
+
46
+ end # class RVG
47
+ end # module Magick
48
+
@@ -0,0 +1,131 @@
1
+ #--
2
+ # $Id: container.rb,v 1.4 2008/02/24 18:26:36 rmagick Exp $
3
+ # Copyright (C) 2008 Timothy P. Hunter
4
+ #++
5
+
6
+ module Magick
7
+ class RVG
8
+
9
+ # Content is simply an Array with a deep_copy method.
10
+ # When unit-testing, it also has a deep_equal method.
11
+ class Content < Array #:nodoc:
12
+
13
+ def deep_copy(h = {})
14
+ me = self.__id__
15
+ copy = h[me]
16
+ unless copy
17
+ copy = self.class.new
18
+ each do |c|
19
+ copy << case
20
+ when c.nil?
21
+ nil
22
+ when c.respond_to?(:deep_copy)
23
+ c.deep_copy(h)
24
+ when c.respond_to?(:dup)
25
+ c.dup rescue c
26
+ else
27
+ c
28
+ end
29
+ end
30
+ copy.freeze if frozen?
31
+ h[me] = copy
32
+ end
33
+ return copy
34
+ end
35
+
36
+ end # class Content
37
+
38
+ # Define a collection of shapes, text, etc. that can be reused.
39
+ # Group objects are _containers_. That is, styles and transforms defined
40
+ # on the group are used by contained objects such as shapes, text, and
41
+ # nested groups unless overridden by a nested container or the object itself.
42
+ # Groups can be reused with the RVG::UseConstructors#use method.
43
+ # Create groups within
44
+ # containers with the RVG::StructureConstructors#g method.
45
+ #
46
+ # Example:
47
+ # # All elements in the group will be translated by 50 in the
48
+ # # x-direction and 10 in the y-direction.
49
+ # rvg.g.translate(50, 10).styles(:stroke=>'red',:fill=>'none') do |grp|
50
+ # # The line will be red.
51
+ # grp.line(10,10, 20,20)
52
+ # # The circle will be blue.
53
+ # grp.circle(10, 20, 20).styles(:stroke=>'blue')
54
+ # end
55
+ class Group
56
+ include Stylable
57
+ include Transformable
58
+ include Embellishable
59
+ include Describable
60
+ include Duplicatable
61
+
62
+ def initialize
63
+ super
64
+ @content = Content.new
65
+ yield(self) if block_given?
66
+ end
67
+
68
+ def add_primitives(gc) #:nodoc:
69
+ gc.push
70
+ add_transform_primitives(gc)
71
+ add_style_primitives(gc)
72
+ @content.each { |element| element.add_primitives(gc) }
73
+ gc.pop
74
+ end
75
+
76
+ # Translate container according to #use arguments
77
+ def ref(x, y, width, height) #:nodoc:
78
+ translate(x, y) if (x != 0 || y != 0)
79
+ end
80
+
81
+ # Append an arbitrary object to the group's content. Called
82
+ # by #use to insert a non-container object into a group.
83
+ def <<(obj) #:nodoc:
84
+ @content << obj
85
+ end
86
+
87
+ end # class Group
88
+
89
+
90
+ # A Use object allows the re-use of RVG and RVG::Group
91
+ # objects within a container. Create a Use object with the
92
+ # RVG::UseConstructors#use method.
93
+ class Use
94
+ include Stylable
95
+ include Transformable
96
+ include Duplicatable
97
+
98
+ # In a container, Use objects are created indirectly via the
99
+ # RVG::UseConstructors#use method.
100
+ # The +x+ and +y+ arguments
101
+ # can be used to specify an additional translation for
102
+ # the group. The +width+ and +height+ arguments specify
103
+ # a width and height for referenced RVG objects.
104
+ def initialize(element, x=0, y=0, width=nil, height=nil)
105
+ super()
106
+
107
+ # If the element is not a group, defs, symbol, or rvg,
108
+ # wrap a group around it so it can get a transform and
109
+ # possibly a new viewport.
110
+ if ! element.respond_to?(:ref)
111
+ @element = Group.new
112
+ @element << element.deep_copy
113
+ else
114
+ @element = element.deep_copy
115
+ end
116
+ @element.ref(x, y, width, height)
117
+ end
118
+
119
+ def add_primitives(gc) #:nodoc:
120
+ gc.push
121
+ add_transform_primitives(gc)
122
+ add_style_primitives(gc)
123
+ @element.add_primitives(gc)
124
+ gc.pop
125
+ end
126
+
127
+ end # class Use
128
+
129
+ end # class RVG
130
+ end # module Magick
131
+
@@ -0,0 +1,56 @@
1
+ module Magick
2
+ class RVG
3
+
4
+ [PathData, Styles, Transforms].each do |c|
5
+ c.class_eval do
6
+ def deep_equal(other)
7
+ if self != other
8
+ puts "#{c.inspect} not equal.\nself:#{self} != other:#{other}"
9
+ return false
10
+ end
11
+ return true
12
+ end
13
+ end
14
+ end
15
+
16
+ [Shape, TextBase, Image, Group, Content, Use, ClipPath, Pattern, self].each do |c|
17
+ c.class_eval do
18
+ def deep_equal(other)
19
+ ivs = self.instance_variables
20
+
21
+ ivs.each do |iv|
22
+ itv = self.instance_variable_get(iv)
23
+ otv = other.instance_variable_get(iv)
24
+ if itv.respond_to?(:deep_equal)
25
+ if itv.equal?(otv)
26
+ puts "#{iv} has deep_equal but self.#{iv} and other.#{iv} are the same object."
27
+ return false
28
+ end
29
+ if !itv.deep_equal(otv)
30
+ puts "Not equal.\nself.#{iv}=#{itv.inspect}\nother.#{iv}=#{otv.inspect}"
31
+ return false
32
+ end
33
+ else
34
+ case itv
35
+ when Float, Symbol, TrueClass, FalseClass, Fixnum, NilClass
36
+ return false if itv != otv
37
+ else
38
+ if itv.equal?(otv)
39
+ puts "#{iv} is dup-able but self.#{iv} and other.#{iv} are the same object."
40
+ return false
41
+ end
42
+ if itv != otv
43
+ puts "Not equal.\nself.#{iv}=#{itv.inspect}\nother.#{iv}=#{otv.inspect}"
44
+ return false
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ return true
51
+ end
52
+ end
53
+ end
54
+
55
+ end # class RVG
56
+ end # module Magick